Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NormalizeUnpackFileModes option to Packer struct #53

Closed
wants to merge 7 commits into from

Conversation

sebasslash
Copy link
Contributor

@sebasslash sebasslash commented Jan 18, 2024

A recent change was introduced that preserves a file's original atime, mtime and mode when unpacked from a tarball. This consequently shifted responsibility to the slug's consumer to ensure each untarred file has the expected permissions. Inevitably this can lead to unpredictable errors, particularly if slugs are created by unknown sources and are expected to be handled uniformly.

This PR aims to add a new packer option, NormalizeUnpackFileModes, that configures go-slug to normalize file modes when unpacking configuration files. This change aims to behave closely to how git normalizes permissions. The permissions for each type of file are encoded as follows:

  • Regular, non-executable: 0644
  • Regular, executable: 0755
  • Directory: 040755
  • Symlink: 0120777

All other file types are unsupported and result in an error: named pipes, char devices, sockets, etc.

Example Usage:

p, err := NewPacker(NormalizeUnpackFileModes(), DereferenceSymlinks())
if err != nil { // do a thing }

// Omitting code to handle packing or loading slug
if err = p.Unpack("/path/to/slug", "/path/to/destination"); err != nil {
  panic("whoops we made a booboo")
}

The inspiration for this change stems from the way git handles files
and normalizes permissions. This change marks the first step to allow
go-slug to similarly resolve file permissions when unpacking tarred
contents. In summary, we normalize all regular files to allow the owner to
read/write the file, while also preserving permissions for executables
and symlinks. This normalization process also disallows certain files like
named pipes, devices, sockets, etc.
@sebasslash sebasslash requested a review from brandonc January 18, 2024 22:20
return i.Typeflag == tar.TypeSymlink
}

// IsDirectory describes whether the file being unpacked is a directory
func (i UnpackInfo) IsDirectory() bool {
func (i *UnpackInfo) IsDirectory() bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you say more about why you're changing these immutable bool-returning IsSomething() methods to a pointer receiver? I thought Go auto-dereferenced, so you can just directly call value methods if you're holding a pointer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally I've followed the styling that disallows mixing receivers (see Go's guidance). So given I needed a pointer receiver to configure an instance of UnpackInfo, I changed all of the methods for consistency.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, okay! Solid answer, thank you.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL

Comment on lines 15 to 16
// Regular represent non-executable files. Please note this is not
// the same as golang regular files, which include executable files.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. Do you think it's worth using a slightly different name than Go does to avoid confusion? If so, I suggest "Plain".

case Regular:
return fs.FileMode(0644), nil
case Dir:
return fs.ModePerm | fs.ModeDir, nil
Copy link
Member

@nfagerlund nfagerlund Jan 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This made me doubt myself and I ran in circles about it for a while, but! I think we actually want directories to be 755 (world read+searchable), not 777 (world read+search+writeable). Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In truth I followed the permissions set by go-git. I wonder if there is a specific use case in git that requires dirs with r+w+x for all groups/users. I think for the purposes of Terraform configuration this would be irrelevant so we can get by with 0755. I will double check this to be sure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 I wonder if there's a mask being applied somewhere later down the chain. Maybe do a real-world test and see what comes out; this is a case where I'm dubious about trusting what the code claims it's doing.

@sebasslash sebasslash force-pushed the sebasslash/ipl-5467_normalize-perms-unpack branch 2 times, most recently from b00a600 to 854fa1c Compare January 29, 2024 22:49
@sebasslash sebasslash force-pushed the sebasslash/ipl-5467_normalize-perms-unpack branch from 854fa1c to cefa5f0 Compare January 29, 2024 22:52
@brandonc
Copy link
Contributor

I don't feel this needs to be a new option. Why wouldn't we make it the default behavior?

@sebasslash sebasslash closed this Feb 8, 2024
@xiehan xiehan deleted the sebasslash/ipl-5467_normalize-perms-unpack branch November 20, 2024 11:16
@xiehan xiehan restored the sebasslash/ipl-5467_normalize-perms-unpack branch November 20, 2024 11:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants