spec icon indicating copy to clipboard operation
spec copied to clipboard

[RFC 0076] Require `CNB_{USER,GROUP}_SID` instead of `CNB_{USER,GROUP}_ID` on windows stack images

Open ekcasey opened this issue 4 years ago • 7 comments

RFC 0076 https://github.com/buildpacks/rfcs/pull/133

  • Replace CNB_USER_ID and CNB_GROUP_ID with CNB_USER_SID and CNB_GROUP_SID on windows stack images
  • Replace -uid and -gid flags with -usid and -gsid flags for builds in windows environments

Motivating context: https://github.com/buildpacks/lifecycle/issues/343

02/17/2021 - Updated to reflect the result of the RFC above

ekcasey avatar Jul 31 '20 15:07 ekcasey

After some digging, it appears there are no straight forward, cross-platform tools for converting SDDL to the binary format used as the header["MSWINDOWS.rawsd"].

The golang implementation calls the Windows API syscall to do convert it: source

Wine has an implementation but that would be a heavy-weight dependency and non-trivial to port to golang: source

I feel like our best bet may be to require to the format of CNB_SECURITY_DESCRIPTOR to be the exact base64-encoded binary format of the MSWINDOWS.rawsd header value. We could potentially provide a tool or powershell example, which runs on Windows and calls the Windows APIs, to convert it.

Which in the image config, would look like:

"config":{
  "Env":[
    "CNB_SECURITY_DESCRIPTOR= AQAAgBQAAAAkAAAAAAAAAAAAAAABAgAAAAAABSAAAAAgAgAAAQIAAAAAAAUgAAAAIAIAAA=="
   ]
}

Which would be generated with:

# for owner: BUILTIN/Administrators group: BUILTIN/Administrators
$sddlValue="O:BAG:BA"
$sddl = (ConvertFrom-SddlString $sddlValue)
$sddlBytes = [byte[]]::New($sddl.RawDescriptor.BinaryLength)
$sddl.RawDescriptor.GetBinaryForm($sddlBytes, 0)
[Convert]::ToBase64String($sddlBytes)
# => AQAAgBQAAAAkAAAAAAAAAAAAAAABAgAAAAAABSAAAAAgAgAAAQIAAAAAAAUgAAAAIAIAAA==

micahyoung avatar Oct 16 '20 12:10 micahyoung

@micahyoung Do we need a cross-platform solution for this? We will only need to convert the string to the binary format on windows right, and therefore we can use the golang implementation?

ekcasey avatar Oct 16 '20 12:10 ekcasey

If I recall, I thought create-builder ~~and package-buildpack~~ sets pack-owned directories on the image which would have these permissions. I'll double-check though.

If this was only needed for lifecycle, we'd be fine with Windows-only though.

Update: here's the spot I was thinking of: https://github.com/buildpacks/pack/blob/96d1cdf9e98b4e9adfdb020c0bb253573a3917a5/internal/builder/builder.go#L541

micahyoung avatar Oct 16 '20 13:10 micahyoung

@micahyoung good point, I was only thinking about the lifecycle/spec use case. I forgot that the platform reads and uses these env vars. create-builder needs to set file ownership (package-buildpack should not because he stack and therefore the user is unknown at the time of packaging).

ekcasey avatar Oct 16 '20 13:10 ekcasey

The binary format is documented and we could potentially invest the time in implement a golang encoder. It would likely have to move out the timeline on this issue however.

There's a couple other C implementations I want to check out as well, though neither seems to have existing golang wrappers ... https://www.samba.org/samba/docs/current/man-html/sharesec.1.html

https://sourceforge.net/projects/ntfs-3g/

micahyoung avatar Oct 16 '20 13:10 micahyoung

@micahyoung Given that this isn't perfectly straight forward, it is probably worth doing a proof-of-concept before committing to a strategy in the spec. I am going to reschedule this from platform API 0.5 to 0.6 to give us more time to explore options.

ekcasey avatar Oct 16 '20 13:10 ekcasey

Good call. I feel user-friendly SDDL format (CNB_SECURITY_DESCRIPTOR="O:BAG:BA") is ideal so I'll keep hacking around at something that can process that into the header rawsd format.

micahyoung avatar Oct 16 '20 13:10 micahyoung