Skip to content

feat add cli option to add credentials files #5900

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Shubhranshu153
Copy link

Description

Add a cli option to pass in credential config file path. This will override DOCKER_CONFIG path used to fetch credential. You can pass a file path or a file descriptor("fd://") or a pipe("pipe://")

Use case:

This will allow clients to configure the cred config location of the buildctl and pass in credentials via file descriptors and pipes as well if they dont want to write it to disk.

Related to issue: #5860

@Shubhranshu153
Copy link
Author

@tonistiigi @AkihiroSuda
When you get a chance take a look.
Thanks.

if err != nil {
return nil, errors.Wrap(err, "parsing file descriptor")
}
f := os.NewFile(uintptr(fd), "")
Copy link

Choose a reason for hiding this comment

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

Does go throw an error here if the file descriptor is above the OS limit (e.g. /proc/sys/fs/file-max or ulimit on Linux)?

Copy link
Author

Choose a reason for hiding this comment

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

I think the open call will fail if it is more than the limit. The newfile itself doesnt throw error.

Copy link
Member

Choose a reason for hiding this comment

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

There is no open if it is a fd. read(2) would fail.

Copy link
Author

Choose a reason for hiding this comment

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

fd is from a open file that is getting inherrited as a child process. if the fd is not inherited it would fail from what i tested which makes sense to me for the use case i am trying.
Do you suggest i check if the fd is valid and open already? @tonistiigi

if err := configFile.LoadFromReader(f); err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("loading config file %s", path))
}
case strings.HasPrefix(path, "pipe://"):
Copy link

Choose a reason for hiding this comment

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

Should this work with Windows pipes? I think they start with \\.\pipe\ typically, but I'm not sure if they're opened like a regular file.

Copy link
Author

Choose a reason for hiding this comment

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

i am not very familiar with using windows pipe, if there is a specific requirement we can implement but at the moment i dont know if we do require it.

Copy link
Member

Choose a reason for hiding this comment

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

@Shubhranshu153 Shubhranshu153 force-pushed the feat-creds-by-fd branch 2 times, most recently from db09cc6 to 7626804 Compare April 10, 2025 00:18
if err := configFile.LoadFromReader(f); err != nil {
return nil, errors.Wrapf(err, "loading config file %s", path)
}
case strings.HasPrefix(path, "pipe://"):
Copy link
Member

Choose a reason for hiding this comment

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

On Linux, pipe:// is probably unneeded and can be just treated in the same way as a regular file

Copy link
Author

Choose a reason for hiding this comment

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

it was more of a logical entry to differentiate, can remove it.

if path == "" {
return nil, fmt.Errorf("credential file path empty")
}
configFile := configfile.New("config-file")
Copy link
Member

Choose a reason for hiding this comment

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

This is a bit scary. There are functions like configFile.Save() that would now write out actual file to this path.

Maybe it would make sense for DockerAuthProviderConfig to take a limited interface that just implements GetAuthConfig(registry) instead? @AkihiroSuda

Copy link
Author

Choose a reason for hiding this comment

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

Does buildkit write back credentials to this file? or its more of a concern with it is possible to write back to the path and as such is a risk itself.

Copy link
Member

Choose a reason for hiding this comment

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

It's more of a concern that we pass full configfile to another component, so we can't really control what methods it is allowed to call. We are passing configfile, but it isn't actually a valid file.

Copy link
Author

Choose a reason for hiding this comment

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

in that case when the further component call it to write it would fail i suppose which is not ideal but is it a risk though as the config file if its a fd then it needs to be called as a child process or else it wont be valid. For pipes it is more tricky i suppose as they can be passed independently.
@tonistiigi @AkihiroSuda

if err != nil {
return nil, errors.Wrap(err, "parsing file descriptor")
}
f := os.NewFile(uintptr(fd), "")
Copy link
Member

Choose a reason for hiding this comment

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

There is no open if it is a fd. read(2) would fail.

if err := configFile.LoadFromReader(f); err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("loading config file %s", path))
}
case strings.HasPrefix(path, "pipe://"):
Copy link
Member

Choose a reason for hiding this comment

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

@Shubhranshu153
Copy link
Author

@tonistiigi
There is no open if it is a fd. read(2) would fail -> Open file descriptor needs to be passed along when a os.exec call is made

Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

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

Linter is failing, and I would still prefer to not pass the whole (fake) configfile.

@Shubhranshu153
Copy link
Author

Shubhranshu153 commented Apr 24, 2025

@tonistiigi

 I would still prefer to not pass the whole (fake) configfile.

When we say pass the whole configfile are we stating the whole configfile struct into DockerAuthProvider and any component that uses DockerAuthProviderConfig has access to this configfile and we cannot control the use of it?

@Shubhranshu153
Copy link
Author

@tonistiigi @AkihiroSuda
Added interface implementing GetAuthConfig(registry) as per suggestion to circumnavigate configfile.Save(). Let me know if this solution works. To safegaurd behaviour may be i can add all the implementation and override Save() if its required.

@@ -32,6 +31,11 @@ import (
"google.golang.org/grpc/status"
)

// ConfigFile Interface exposes GetAuthConfig method.
type ConfigFile interface {
Copy link
Member

Choose a reason for hiding this comment

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

AuthConfigProvider

return err
}

func processCredentialConfigFile(path string) (*configfile.ConfigFile, error) {
Copy link
Member

Choose a reason for hiding this comment

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

This should return the interface type

Copy link
Author

Choose a reason for hiding this comment

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

Thanks changed it.

Signed-off-by: Shubharanshu Mahapatra <shubhum@amazon.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants