forked from k3s-io/k3s
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Harrison Affel <harrisonaffel@gmail.com>
- Loading branch information
1 parent
1cd7986
commit 1d22b69
Showing
4 changed files
with
202 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
//go:build windows | ||
// +build windows | ||
|
||
package acl | ||
|
||
import ( | ||
"fmt" | ||
"golang.org/x/sys/windows" | ||
"unsafe" | ||
) | ||
|
||
// TODO: Remove in favor of the rancher/permissions repository once that is setup | ||
|
||
func BuiltinAdministratorsSID() *windows.SID { | ||
return mustGetSid(windows.WinBuiltinAdministratorsSid) | ||
} | ||
|
||
func LocalSystemSID() *windows.SID { | ||
return mustGetSid(windows.WinLocalSystemSid) | ||
} | ||
|
||
func mustGetSid(sidType windows.WELL_KNOWN_SID_TYPE) *windows.SID { | ||
sid, err := windows.CreateWellKnownSid(sidType) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return sid | ||
} | ||
|
||
// GrantSid creates an EXPLICIT_ACCESS instance granting permissions to the provided SID. | ||
func GrantSid(accessPermissions windows.ACCESS_MASK, sid *windows.SID) windows.EXPLICIT_ACCESS { | ||
return windows.EXPLICIT_ACCESS{ | ||
AccessPermissions: accessPermissions, | ||
AccessMode: windows.GRANT_ACCESS, | ||
Inheritance: windows.SUB_CONTAINERS_AND_OBJECTS_INHERIT, | ||
Trustee: windows.TRUSTEE{ | ||
TrusteeForm: windows.TRUSTEE_IS_SID, | ||
TrusteeValue: windows.TrusteeValueFromSID(sid), | ||
}, | ||
} | ||
} | ||
|
||
// Apply performs both Chmod and Chown at the same time, where the filemode's owner and group will correspond to | ||
// the provided owner and group (or the current owner and group, if they are set to nil) | ||
func Apply(path string, owner *windows.SID, group *windows.SID, access ...windows.EXPLICIT_ACCESS) error { | ||
if path == "" { | ||
return fmt.Errorf("path cannot be empty") | ||
} | ||
return apply(path, owner, group, access...) | ||
} | ||
|
||
// apply performs a Chmod (if owner and group are provided) and sets a custom ACL based on the provided EXPLICIT_ACCESS rules | ||
// To create EXPLICIT_ACCESS rules, see the helper functions in pkg/access | ||
func apply(path string, owner *windows.SID, group *windows.SID, access ...windows.EXPLICIT_ACCESS) error { | ||
// assemble arguments | ||
args := securityArgs{ | ||
path: path, | ||
owner: owner, | ||
group: group, | ||
access: access, | ||
} | ||
|
||
securityInfo := args.ToSecurityInfo() | ||
if securityInfo == 0 { | ||
// nothing to change | ||
return nil | ||
} | ||
dacl, err := args.ToDACL() | ||
if err != nil { | ||
return err | ||
} | ||
return windows.SetNamedSecurityInfo( | ||
path, | ||
windows.SE_FILE_OBJECT, | ||
securityInfo, | ||
owner, | ||
group, | ||
dacl, | ||
nil, | ||
) | ||
} | ||
|
||
type securityArgs struct { | ||
path string | ||
|
||
owner *windows.SID | ||
group *windows.SID | ||
|
||
access []windows.EXPLICIT_ACCESS | ||
} | ||
|
||
func (a *securityArgs) ToSecurityInfo() windows.SECURITY_INFORMATION { | ||
var securityInfo windows.SECURITY_INFORMATION | ||
|
||
if a.owner != nil { | ||
// override owner | ||
securityInfo |= windows.OWNER_SECURITY_INFORMATION | ||
} | ||
|
||
if a.group != nil { | ||
// override group | ||
securityInfo |= windows.GROUP_SECURITY_INFORMATION | ||
} | ||
|
||
if len(a.access) != 0 { | ||
// override DACL | ||
securityInfo |= windows.DACL_SECURITY_INFORMATION | ||
securityInfo |= windows.PROTECTED_DACL_SECURITY_INFORMATION | ||
} | ||
|
||
return securityInfo | ||
} | ||
|
||
func (a *securityArgs) ToSecurityAttributes() (*windows.SecurityAttributes, error) { | ||
// define empty security descriptor | ||
sd, err := windows.NewSecurityDescriptor() | ||
if err != nil { | ||
return nil, err | ||
} | ||
err = sd.SetOwner(a.owner, false) | ||
if err != nil { | ||
return nil, err | ||
} | ||
err = sd.SetGroup(a.group, false) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// define security attributes using descriptor | ||
var sa windows.SecurityAttributes | ||
sa.Length = uint32(unsafe.Sizeof(sa)) | ||
sa.SecurityDescriptor = sd | ||
|
||
if len(a.access) == 0 { | ||
// security attribute should simply inherit parent rules | ||
sa.InheritHandle = 1 | ||
return &sa, nil | ||
} | ||
|
||
// apply provided access rules to the DACL | ||
dacl, err := a.ToDACL() | ||
if err != nil { | ||
return nil, err | ||
} | ||
err = sd.SetDACL(dacl, true, false) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// set the protected DACL flag to prevent the DACL of the security descriptor from being modified by inheritable ACEs | ||
// (i.e. prevent parent folders from modifying this ACL) | ||
err = sd.SetControl(windows.SE_DACL_PROTECTED, windows.SE_DACL_PROTECTED) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &sa, nil | ||
} | ||
|
||
func (a *securityArgs) ToDACL() (*windows.ACL, error) { | ||
if len(a.access) == 0 { | ||
// No rules were specified | ||
return nil, nil | ||
} | ||
return windows.ACLFromEntries(a.access, nil) | ||
} |