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

container driver: copy ca and user tls registries certs #787

Merged
merged 1 commit into from Oct 28, 2021

Conversation

crazy-max
Copy link
Member

@crazy-max crazy-max commented Sep 29, 2021

Fixes docker/build-push-action#436
Fixes moby/buildkit#1055
Fixes #567
Fixes #80
Fixes #306
Fixes #455

Follow-up moby/buildkit#2361 and moby/buildkit#2377

Since moby/buildkit#1410 we can provide rootCA and keyPairs for registries but we have to copy those certs in the container after the builder is created.

This PR allows to copy certificates to the container when a docker-container builder is created by reading the buildkitd toml configuration. Wonder if this should be opt-in or not for security purpose.

Same logic might be used upstream for buildctl moby/buildkit#1050.

Signed-off-by: CrazyMax crazy-max@users.noreply.github.com

@tonistiigi tonistiigi added this to the v0.7.0 milestone Oct 18, 2021
@crazy-max crazy-max changed the title Copy CA and user TLS registries certs to the container container driver: copy ca and user tls registries certs Oct 18, 2021
@crazy-max crazy-max force-pushed the inject-certs branch 2 times, most recently from 6f611e6 to 8c8ac92 Compare October 18, 2021 21:00
@@ -205,6 +213,211 @@ func (d *Driver) copyLogs(ctx context.Context, l progress.SubLogger) error {
return rc.Close()
}

// copyToContainer is based on the implementation from docker/cli
// https://github.com/docker/cli/blob/master/cli/command/container/cp.go
func (d *Driver) copyToContainer(ctx context.Context, srcPath string, dstPath string) error {
Copy link
Member

Choose a reason for hiding this comment

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

Could we reuse some of this code in k8s driver? cc @morlay

Copy link
Collaborator

@morlay morlay Oct 20, 2021

Choose a reason for hiding this comment

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

copyBuildKitConfToContainer could.

In k8s, we have to read file data and store it in ConfigMap or Secrets, and mount it into running containter.

I prefix add an interface for Driver to add files, like

inteface Driver {
   AddFile(mountPath string, data []byte, secure bool)
}

Then diffrent drivers do each mounting.

And copyBuildKitConfToContainer(...) could be copyBuildKitConfForDriver(d Dirver, ....) to reuse

Copy link
Member

Choose a reason for hiding this comment

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

Actually, this part might be fine to be driver-specific but the part that modifies the toml file and copies certs under .docker should not be specific to the driver but shared.

Copy link
Collaborator

@morlay morlay Oct 20, 2021

Choose a reason for hiding this comment

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

So let driver have ability to add file will be useful.

if the driver not need those files, it could skip AddFile

But driver like docker-container and kubernetes need, it could be easy to AddFile with different ways.

Copy link
Collaborator

@morlay morlay Oct 20, 2021

Choose a reason for hiding this comment

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

At least, copyBuildKitConfToContainer is needed to kubernetes driver too.

But consider to read file data to memory and write it the temp path in copyToContainer (may rename as AddFile).

cc @crazy-max

Copy link
Collaborator

@morlay morlay Oct 22, 2021

Choose a reason for hiding this comment

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

@tonistiigi

I don't understand why you have two volumes in your example when they both modify /etc/buildkit

it is not modify /etc/buildkit, it is modify files and sub dirs of /etc/buildkit.

if only mount single /etc/buildkit, we have to store toml and files in ConfigMap like

data:
    buildkit.toml:  xxx
    key.pem: xxx  
    certs.pem: xxx

The mounted /etc/buildkit will be

/etc/buildkit/
  buildkit.toml
  key.pem
  certs.pem

With my example, it could mount any file in any location.

even put all files under /etc/buildkit, it could be same as container-driver did

/etc/buildkit/
  certs/myregistry.io/
     key.pem
     certs.pem
  buildkit.toml

Copy link
Collaborator

Choose a reason for hiding this comment

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

we can't copy a file in a folder that does not exist in the container with the CopyToContainer Docker API.

Yes, but we could write to temp files before CopyToContainer in AddFile

If worry about copy cost. we could design the API like https://docs.min.io/docs/golang-client-api-reference.html#PutObject

type PutFileOptions struct {
   Secure bool
}

type Driver interface {
   PutFile(ctx context.Context, containerAbsPath string, r io.Reader, putOpts PutFileOptions) error
}

Copy link
Member

Choose a reason for hiding this comment

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

So configmap can not contain subdirectories?

Copy link
Collaborator

@morlay morlay Oct 22, 2021

Choose a reason for hiding this comment

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

@tonistiigi Yes. / is not allowed in ConfigMap data key, it could be a flatten KV.

For subdirectories, we have to rename the absolute path, and resolve it back with volumes and volumeMounts like my example did.

This why I prefer have a PutFile() interface to make driver could do mounting files,
Then we could just convert and mount files for diffrent drivers in PutFile().

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes we could use an interface but like @tonistiigi said we can't use the same paths defined on the host for ca and user tls registries certs inside the container, that's why the buildkitd toml needs to be modified anyway.

Maybe we could impl a buildkitd.override.toml on BuildKit.

@crazy-max crazy-max force-pushed the inject-certs branch 3 times, most recently from c1bc817 to 3965144 Compare October 21, 2021 09:28
@crazy-max crazy-max marked this pull request as ready for review October 21, 2021 16:52
util/bkutil/config.go Outdated Show resolved Hide resolved
util/bkutil/container.go Outdated Show resolved Hide resolved
driver/docker-container/driver.go Outdated Show resolved Hide resolved
}

// Temp dir that will be copied to the container
tmpDir, err := os.MkdirTemp("", "buildkitd-config")
Copy link
Member

Choose a reason for hiding this comment

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

why temp directory? just save it under .docker/buildx or do you want to do this separately?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes will do that in a follow-up to keep the current state

util/bkutil/container.go Outdated Show resolved Hide resolved
util/bkutil/container.go Outdated Show resolved Hide resolved
util/bkutil/container.go Outdated Show resolved Hide resolved
driver/docker-container/driver.go Outdated Show resolved Hide resolved
driver/docker-container/driver.go Outdated Show resolved Hide resolved
if err != nil {
return err
}
defer preparedArchive.Close()
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we need any of this between 218-278. Just calling archive.Tar to get ReadCloser should be enough for this case.

Copy link
Member

Choose a reason for hiding this comment

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

^

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

Copy link
Member

Choose a reason for hiding this comment

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

I think you can remove more. As I said, I think only a single archive.Tar call is needed here.

@crazy-max crazy-max force-pushed the inject-certs branch 3 times, most recently from ce4ae00 to 806ae3d Compare October 27, 2021 10:41
@crazy-max crazy-max force-pushed the inject-certs branch 2 times, most recently from f8d0a5f to 3abe6f8 Compare October 28, 2021 09:15
@@ -205,6 +202,28 @@ func (d *Driver) copyLogs(ctx context.Context, l progress.SubLogger) error {
return rc.Close()
}

func (d *Driver) copyToContainer(ctx context.Context, srcPath string, dstDir string) error {
srcPath, err := resolveLocalPath(srcPath)
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is needed either. Nor the /. prefix.

if err != nil {
return err
}
srcArchive, err := dockerarchive.TarWithOptions(srcPath, &dockerarchive.TarOptions{})
Copy link
Member

Choose a reason for hiding this comment

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

nit: dockerarchive.Tar simpler for this case

Copy link
Member Author

@crazy-max crazy-max Oct 28, 2021

Choose a reason for hiding this comment

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

dockerarchive.Tar requires a Compression arg, that's why I use dockerarchive.TarWithOptions instead. That API feels odd and should be changed I think.

Copy link
Member

Choose a reason for hiding this comment

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

dockerarchive.Uncompressed

}
defer srcArchive.Close()
return d.DockerAPI.CopyToContainer(ctx, d.Name, dstDir, srcArchive, dockertypes.CopyToContainerOptions{
AllowOverwriteDirWithFile: false,
Copy link
Member

Choose a reason for hiding this comment

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

If it is default anyway then don't set it.

@crazy-max crazy-max force-pushed the inject-certs branch 2 times, most recently from 64b8ffe to 6626f1c Compare October 28, 2021 17:55
@crazy-max
Copy link
Member Author

@tonistiigi I will add tests in a follow-up.

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment