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

Authenticate for CacheFrom via input credentials on Image #500

Merged
merged 5 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion provider/cmd/pulumi-resource-docker/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3062,7 +3062,7 @@
},
"cacheFrom": {
"$ref": "#/types/docker:index/cacheFrom:CacheFrom",
"description": "A list of images to use as build cache"
"description": "A list of image names to use as build cache. Images provided must have a cache manifest. Must provide authentication to cache registry."
},
"context": {
"type": "string",
Expand Down
113 changes: 60 additions & 53 deletions provider/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,26 @@ func (p *dockerNativeProvider) dockerBuild(ctx context.Context,
return "", nil, err
}

auths, err := cfg.GetAllCredentials()
if err != nil {
return "", nil, err
}
// read auths to a map of authConfigs for the build options to consume
authConfigs := make(map[string]types.AuthConfig, len(auths))
for k, auth := range auths {
authConfigs[k] = types.AuthConfig(auth)
authConfigs := make(map[string]types.AuthConfig)
var regAuth types.AuthConfig

// sign into registry if we're pushing or setting CacheFrom
// TODO: add functionality for additional registry caches not associated with the stack image
// See: https://github.com/pulumi/pulumi-docker/issues/497
if len(img.Build.CachedImages) > 0 || !img.SkipPush {
auth, msg, err := getRegistryAuth(img, cfg)
if err != nil {
return "", nil, err
}
if msg != "" {
err = p.host.Log(ctx, "warning", urn, msg)
if err != nil {
return "", nil, err
}
}
authConfigs[auth.ServerAddress] = auth // for image cache
regAuth = auth // for image push
}

// make the build options
opts := types.ImageBuildOptions{
Dockerfile: img.Build.Dockerfile,
Expand Down Expand Up @@ -183,50 +193,7 @@ func (p *dockerNativeProvider) dockerBuild(ctx context.Context,
return "", nil, err
}

// authentication for registry push
// we check if the user set creds in the Pulumi program, and use those preferentially,
// otherwise we use host machine creds via authConfigs.
var pushAuthConfig types.AuthConfig

if img.Registry.Username != "" && img.Registry.Password != "" {
pushAuthConfig.Username = img.Registry.Username
pushAuthConfig.Password = img.Registry.Password
pushAuthConfig.ServerAddress, err = getRegistryAddrForAuth(img.Registry.Server, img.Name)
if err != nil {
return "", nil, err
}

} else {
// send warning if user is attempting to use in-program credentials
if img.Registry.Username == "" && img.Registry.Password != "" {
msg := "username was not set, although password was; using host credentials file"
err = p.host.Log(ctx, "warning", urn, msg)
if err != nil {
return "", nil, err
}
}
if img.Registry.Password == "" && img.Registry.Username != "" {
msg := "password was not set, although username was; using host credentials file"
err = p.host.Log(ctx, "warning", urn, msg)
if err != nil {
return "", nil, err
}
}

registryServer, err := getRegistryAddrForAuth(img.Registry.Server, img.Name)
if err != nil {
return "", nil, err
}

cliPushAuthConfig, err := cfg.GetAuthConfig(registryServer)
if err != nil {
return "", nil, err
}

pushAuthConfig = types.AuthConfig(cliPushAuthConfig)
}

authConfigBytes, err := json.Marshal(pushAuthConfig)
authConfigBytes, err := json.Marshal(regAuth)

if err != nil {
return "", nil, fmt.Errorf("error parsing authConfig: %v", err)
Expand Down Expand Up @@ -417,6 +384,46 @@ func getDefaultDockerConfig() (*configfile.ConfigFile, error) {
return cfg, nil
}

func getRegistryAuth(img Image, cfg *configfile.ConfigFile) (types.AuthConfig, string, error) {
// authentication for registry push or cache pull
// we check if the user set creds in the Pulumi program, and use those preferentially,
// otherwise we use host machine creds via authConfigs.
var regAuthConfig types.AuthConfig
var msg string

if img.Registry.Username != "" && img.Registry.Password != "" {
regAuthConfig.Username = img.Registry.Username
regAuthConfig.Password = img.Registry.Password
serverAddr, err := getRegistryAddrForAuth(img.Registry.Server, img.Name)
if err != nil {
return regAuthConfig, msg, err
}
regAuthConfig.ServerAddress = serverAddr

} else {
// send warning if user is attempting to use in-program credentials
if img.Registry.Username == "" && img.Registry.Password != "" {
msg = "username was not set, although password was; using host credentials file"
}
if img.Registry.Password == "" && img.Registry.Username != "" {
msg = "password was not set, although username was; using host credentials file"
}

registryServer, err := getRegistryAddrForAuth(img.Registry.Server, img.Name)
if err != nil {
return regAuthConfig, msg, err
}

cliPushAuthConfig, err := cfg.GetAuthConfig(registryServer)
if err != nil {
return regAuthConfig, msg, err
}

regAuthConfig = types.AuthConfig(cliPushAuthConfig)
}
return regAuthConfig, msg, nil
}

// Because the authConfigs provided by the host may return URIs with the `https://` scheme in the
// map keys, `getRegistryAddrForAuth` ensures we return either the legacy Docker IndexServer's URI,
// which is special cased, or a registry hostname.
Expand Down
5 changes: 4 additions & 1 deletion provider/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,10 @@ func Provider() tfbridge.ProviderInfo {
Default: "Dockerfile",
},
"cacheFrom": {
Description: "A list of images to use as build cache",
Description: "A list of image names to use as build cache. " +
"Images provided must have a cache manifest. " +
"Must provide authentication to cache registry.",

TypeSpec: schema.TypeSpec{
Ref: "#/types/docker:index/cacheFrom:CacheFrom",
},
Expand Down
2 changes: 1 addition & 1 deletion sdk/dotnet/Inputs/DockerBuildArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public InputMap<string> Args
public Input<Pulumi.Docker.BuilderVersion>? BuilderVersion { get; set; }

/// <summary>
/// A list of images to use as build cache
/// A list of image names to use as build cache. Images provided must have a cache manifest. Must provide authentication to cache registry.
/// </summary>
[Input("cacheFrom")]
public Input<Inputs.CacheFromArgs>? CacheFrom { get; set; }
Expand Down
6 changes: 3 additions & 3 deletions sdk/go/docker/pulumiTypes.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ public Optional<Output<BuilderVersion>> builderVersion() {
}

/**
* A list of images to use as build cache
* A list of image names to use as build cache. Images provided must have a cache manifest. Must provide authentication to cache registry.
*
*/
@Import(name="cacheFrom")
private @Nullable Output<CacheFromArgs> cacheFrom;

/**
* @return A list of images to use as build cache
* @return A list of image names to use as build cache. Images provided must have a cache manifest. Must provide authentication to cache registry.
*
*/
public Optional<Output<CacheFromArgs>> cacheFrom() {
Expand Down Expand Up @@ -201,7 +201,7 @@ public Builder builderVersion(BuilderVersion builderVersion) {
}

/**
* @param cacheFrom A list of images to use as build cache
* @param cacheFrom A list of image names to use as build cache. Images provided must have a cache manifest. Must provide authentication to cache registry.
*
* @return builder
*
Expand All @@ -212,7 +212,7 @@ public Builder cacheFrom(@Nullable Output<CacheFromArgs> cacheFrom) {
}

/**
* @param cacheFrom A list of images to use as build cache
* @param cacheFrom A list of image names to use as build cache. Images provided must have a cache manifest. Must provide authentication to cache registry.
*
* @return builder
*
Expand Down
2 changes: 1 addition & 1 deletion sdk/nodejs/types/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ export interface DockerBuild {
*/
builderVersion?: pulumi.Input<enums.BuilderVersion>;
/**
* A list of images to use as build cache
* A list of image names to use as build cache. Images provided must have a cache manifest. Must provide authentication to cache registry.
*/
cacheFrom?: pulumi.Input<inputs.CacheFrom>;
/**
Expand Down
4 changes: 2 additions & 2 deletions sdk/python/pulumi_docker/_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4065,7 +4065,7 @@ def __init__(__self__, *,
The Docker build context
:param pulumi.Input[Mapping[str, pulumi.Input[str]]] args: An optional map of named build-time argument variables to set during the Docker build. This flag allows you to pass build-time variablesthat can be accessed like environment variables inside the RUN instruction.
:param pulumi.Input['BuilderVersion'] builder_version: The version of the Docker builder.
:param pulumi.Input['CacheFromArgs'] cache_from: A list of images to use as build cache
:param pulumi.Input['CacheFromArgs'] cache_from: A list of image names to use as build cache. Images provided must have a cache manifest. Must provide authentication to cache registry.
:param pulumi.Input[str] context: The path to the build context to use.
:param pulumi.Input[str] dockerfile: The path to the Dockerfile to use.
:param pulumi.Input[str] platform: The architecture of the platform you want to build this image for, e.g. `linux/arm64`.
Expand Down Expand Up @@ -4120,7 +4120,7 @@ def builder_version(self, value: Optional[pulumi.Input['BuilderVersion']]):
@pulumi.getter(name="cacheFrom")
def cache_from(self) -> Optional[pulumi.Input['CacheFromArgs']]:
"""
A list of images to use as build cache
A list of image names to use as build cache. Images provided must have a cache manifest. Must provide authentication to cache registry.
"""
return pulumi.get(self, "cache_from")

Expand Down