class Chef::Resource::WindowsShare

Public Instance Methods

bool_string(bool) click to toggle source

convert True/False into “$True” & “$False”

# File lib/chef/resource/windows_share.rb, line 330
def bool_string(bool)
  # bool ? 1 : 0
  bool ? "$true" : "$false"
end
create_share() click to toggle source
# File lib/chef/resource/windows_share.rb, line 255
def create_share
  raise "#{new_resource.path} is missing or not a directory. Shares cannot be created if the path doesn't first exist." unless ::File.directory? new_resource.path

  share_cmd = "New-SmbShare -Name '#{new_resource.share_name}' -Path '#{Chef::Util::PathHelper.cleanpath(new_resource.path)}' -Description '#{new_resource.description}' -ConcurrentUserLimit #{new_resource.concurrent_user_limit} -CATimeout #{new_resource.ca_timeout} -EncryptData:#{bool_string(new_resource.encrypt_data)} -ContinuouslyAvailable:#{bool_string(new_resource.continuously_available)}"
  share_cmd << " -ScopeName #{new_resource.scope_name}" unless new_resource.scope_name == "*" # passing * causes the command to fail
  share_cmd << " -Temporary:#{bool_string(new_resource.temporary)}" if new_resource.temporary # only set true

  Chef::Log.debug("Running '#{share_cmd}' to create the share")
  powershell_exec!(share_cmd)

  # New-SmbShare adds the "Everyone" user with read access no matter what so we need to remove it
  # before we add our permissions
  revoke_user_permissions(["Everyone"])
end
delete_share() click to toggle source
# File lib/chef/resource/windows_share.rb, line 239
def delete_share
  delete_command = "Remove-SmbShare -Name '#{new_resource.share_name}' -Force"

  Chef::Log.debug("Running '#{delete_command}' to remove the share")
  powershell_exec!(delete_command)
end
different_path?() click to toggle source
# File lib/chef/resource/windows_share.rb, line 232
def different_path?
  return false if current_resource.nil? # going from nil to something isn't different for our concerns
  return false if current_resource.path == Chef::Util::PathHelper.cleanpath(new_resource.path)

  true
end
parse_permissions(json_results) click to toggle source

given the string output of Get-SmbShareAccess parse out arrays of full access users, change users, and read only users

# File lib/chef/resource/windows_share.rb, line 169
def parse_permissions(json_results)
  json_results = [json_results] unless json_results.is_a?(Array) # single result is not an array

  f_users = []
  c_users = []
  r_users = []

  json_results.each do |perm|
    next unless perm["AccessControlType"] == 0 # allow

    case perm["AccessRight"]
    when 0 then f_users << stripped_account(perm["AccountName"]) # 0 full control
    when 1 then c_users << stripped_account(perm["AccountName"]) # 1 == change
    when 2 then r_users << stripped_account(perm["AccountName"]) # 2 == read
    end
  end
  [f_users, c_users, r_users]
end
permissions_need_update?(type) click to toggle source

determine if permissions need to be updated. Brand new share with no permissions defined: no Brand new share with permissions defined: yes Existing share with differing permissions: yes

@param [String] type the permissions type (Full, Read, or Change)

# File lib/chef/resource/windows_share.rb, line 305
def permissions_need_update?(type)
  property_name = "#{type}_users"

  # brand new share, but nothing to set
  return false if current_resource.nil? && new_resource.send(property_name).empty?

  # brand new share with new permissions to set
  return true if current_resource.nil? && !new_resource.send(property_name).empty?

  # there's a difference between the current and desired state
  return true unless (new_resource.send(property_name) - current_resource.send(property_name)).empty?

  # anything else
  false
end
revoke_user_permissions(users) click to toggle source

revoke user permissions from a share @param [Array] users

# File lib/chef/resource/windows_share.rb, line 323
def revoke_user_permissions(users)
  revoke_command = "Revoke-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{users.join('","')}\" -Force"
  Chef::Log.debug("Running '#{revoke_command}' to revoke share permissions")
  powershell_exec!(revoke_command)
end
stripped_account(name) click to toggle source

local names are returned from Get-SmbShareAccess in the full format MACHINE\NAME but users of this resource would simply say NAME so we need to strip the values for comparison

# File lib/chef/resource/windows_share.rb, line 190
def stripped_account(name)
  name.slice!("#{node["hostname"]}\\")
  name
end
update_permissions() click to toggle source

update existing permissions on a share

# File lib/chef/resource/windows_share.rb, line 282
def update_permissions
  # revoke any users that had something, but now has nothing
  revoke_user_permissions(users_to_revoke) unless users_to_revoke.empty?

  # set permissions for each of the permission types
  %w{full read change}.each do |perm_type|
    # set permissions for a brand new share OR
    # update permissions if the current state and desired state differ
    next unless permissions_need_update?(perm_type)

    grant_command = "Grant-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{new_resource.send("#{perm_type}_users").join('","')}\" -Force -AccessRight #{perm_type}"

    Chef::Log.debug("Running '#{grant_command}' to update the share permissions")
    powershell_exec!(grant_command)
  end
end
update_share() click to toggle source
# File lib/chef/resource/windows_share.rb, line 246
def update_share
  update_command = "Set-SmbShare -Name '#{new_resource.share_name}' -Description '#{new_resource.description}'  -ConcurrentUserLimit #{new_resource.concurrent_user_limit} -CATimeout #{new_resource.ca_timeout} -EncryptData:#{bool_string(new_resource.encrypt_data)} -ContinuouslyAvailable:#{bool_string(new_resource.continuously_available)} -Force"
  update_command << " -ScopeName #{new_resource.scope_name}" unless new_resource.scope_name == "*" # passing * causes the command to fail
  update_command << " -Temporary:#{bool_string(new_resource.temporary)}" if new_resource.temporary # only set true

  Chef::Log.debug("Running '#{update_command}' to update the share")
  powershell_exec!(update_command)
end
users_to_revoke() click to toggle source

determine what users in the current state don't exist in the desired state users/groups will have their permissions updated with the same command that sets it, but removes must be performed with Revoke-SmbShareAccess

# File lib/chef/resource/windows_share.rb, line 273
def users_to_revoke
  @users_to_revoke ||= if current_resource.nil?
                         []
                       else # if it exists then calculate the current to new resource diffs
                         (current_resource.full_users + current_resource.change_users + current_resource.read_users) - (new_resource.full_users + new_resource.change_users + new_resource.read_users)
                       end
end