Skip to content

Commit 6795af2

Browse files
feat: support ENVBUILDER_GIT_SSH_PRIVATE_KEY_BASE64 (#62)
1 parent 311f01b commit 6795af2

File tree

6 files changed

+95
-25
lines changed

6 files changed

+95
-25
lines changed

docs/resources/cached_image.md

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ The cached image resource can be used to retrieve a cached image produced by env
3737
- `git_clone_single_branch` (Boolean) (Envbuilder option) Clone only a single branch of the Git repository.
3838
- `git_http_proxy_url` (String) (Envbuilder option) The URL for the HTTP proxy. This is optional.
3939
- `git_password` (String, Sensitive) (Envbuilder option) The password to use for Git authentication. This is optional.
40+
- `git_ssh_private_key_base64` (String, Sensitive) (Envbuilder option) Base64 encoded SSH private key to be used for Git authentication.
4041
- `git_ssh_private_key_path` (String) (Envbuilder option) Path to an SSH private key to be used for Git authentication.
4142
- `git_username` (String) (Envbuilder option) The username to use for Git authentication. This is optional.
4243
- `ignore_paths` (List of String) (Envbuilder option) The comma separated list of paths to ignore when building the workspace.

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20240702054557-aa55
1010

1111
require (
1212
github.com/GoogleContainerTools/kaniko v1.9.2
13-
github.com/coder/envbuilder v1.0.3
13+
github.com/coder/envbuilder v1.0.4
1414
github.com/coder/serpent v0.8.0
1515
github.com/docker/docker v26.1.5+incompatible
1616
github.com/gliderlabs/ssh v0.3.7

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoC
186186
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
187187
github.com/coder/coder/v2 v2.10.1-0.20240704130443-c2d44d16a352 h1:L/EjCuZxs5tOcqqCaASj/nu65TRYEFcTt8qRQfHZXX0=
188188
github.com/coder/coder/v2 v2.10.1-0.20240704130443-c2d44d16a352/go.mod h1:P1KoQSgnKEAG6Mnd3YlGzAophty+yKA9VV48LpfNRvo=
189-
github.com/coder/envbuilder v1.0.3 h1:Ne2s+JBjGXwdO8PoNBEtgIos1a+VFB2iSuOBQHj+cFA=
190-
github.com/coder/envbuilder v1.0.3/go.mod h1:CkP/qKzWmK14I/aSPwEXoEHlss7OqYDmaM8Q7rDhwt8=
189+
github.com/coder/envbuilder v1.0.4 h1:27DFtKhgsode5I0kBPTCHuzG88Zpny27OVvXOuA/zso=
190+
github.com/coder/envbuilder v1.0.4/go.mod h1:CkP/qKzWmK14I/aSPwEXoEHlss7OqYDmaM8Q7rDhwt8=
191191
github.com/coder/kaniko v0.0.0-20240925122543-caa18967f374 h1:/cyXf0vTSwFh7evQqeWHXXl14aRfC4CsNIYxOenJytQ=
192192
github.com/coder/kaniko v0.0.0-20240925122543-caa18967f374/go.mod h1:XoTDIhNF0Ll4tLmRYdOn31udU9w5zFrY2PME/crSRCA=
193193
github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 h1:3A0ES21Ke+FxEM8CXx9n47SZOKOpgSE1bbJzlE4qPVs=

internal/provider/cached_image_resource.go

+28-22
Original file line numberDiff line numberDiff line change
@@ -49,28 +49,29 @@ type CachedImageResourceModel struct {
4949
CacheRepo types.String `tfsdk:"cache_repo"`
5050
GitURL types.String `tfsdk:"git_url"`
5151
// Optional "inputs".
52-
BaseImageCacheDir types.String `tfsdk:"base_image_cache_dir"`
53-
BuildContextPath types.String `tfsdk:"build_context_path"`
54-
CacheTTLDays types.Int64 `tfsdk:"cache_ttl_days"`
55-
DevcontainerDir types.String `tfsdk:"devcontainer_dir"`
56-
DevcontainerJSONPath types.String `tfsdk:"devcontainer_json_path"`
57-
DockerfilePath types.String `tfsdk:"dockerfile_path"`
58-
DockerConfigBase64 types.String `tfsdk:"docker_config_base64"`
59-
ExitOnBuildFailure types.Bool `tfsdk:"exit_on_build_failure"`
60-
ExtraEnv types.Map `tfsdk:"extra_env"`
61-
FallbackImage types.String `tfsdk:"fallback_image"`
62-
GitCloneDepth types.Int64 `tfsdk:"git_clone_depth"`
63-
GitCloneSingleBranch types.Bool `tfsdk:"git_clone_single_branch"`
64-
GitHTTPProxyURL types.String `tfsdk:"git_http_proxy_url"`
65-
GitPassword types.String `tfsdk:"git_password"`
66-
GitSSHPrivateKeyPath types.String `tfsdk:"git_ssh_private_key_path"`
67-
GitUsername types.String `tfsdk:"git_username"`
68-
IgnorePaths types.List `tfsdk:"ignore_paths"`
69-
Insecure types.Bool `tfsdk:"insecure"`
70-
RemoteRepoBuildMode types.Bool `tfsdk:"remote_repo_build_mode"`
71-
SSLCertBase64 types.String `tfsdk:"ssl_cert_base64"`
72-
Verbose types.Bool `tfsdk:"verbose"`
73-
WorkspaceFolder types.String `tfsdk:"workspace_folder"`
52+
BaseImageCacheDir types.String `tfsdk:"base_image_cache_dir"`
53+
BuildContextPath types.String `tfsdk:"build_context_path"`
54+
CacheTTLDays types.Int64 `tfsdk:"cache_ttl_days"`
55+
DevcontainerDir types.String `tfsdk:"devcontainer_dir"`
56+
DevcontainerJSONPath types.String `tfsdk:"devcontainer_json_path"`
57+
DockerfilePath types.String `tfsdk:"dockerfile_path"`
58+
DockerConfigBase64 types.String `tfsdk:"docker_config_base64"`
59+
ExitOnBuildFailure types.Bool `tfsdk:"exit_on_build_failure"`
60+
ExtraEnv types.Map `tfsdk:"extra_env"`
61+
FallbackImage types.String `tfsdk:"fallback_image"`
62+
GitCloneDepth types.Int64 `tfsdk:"git_clone_depth"`
63+
GitCloneSingleBranch types.Bool `tfsdk:"git_clone_single_branch"`
64+
GitHTTPProxyURL types.String `tfsdk:"git_http_proxy_url"`
65+
GitPassword types.String `tfsdk:"git_password"`
66+
GitSSHPrivateKeyPath types.String `tfsdk:"git_ssh_private_key_path"`
67+
GitSSHPrivateKeyBase64 types.String `tfsdk:"git_ssh_private_key_base64"`
68+
GitUsername types.String `tfsdk:"git_username"`
69+
IgnorePaths types.List `tfsdk:"ignore_paths"`
70+
Insecure types.Bool `tfsdk:"insecure"`
71+
RemoteRepoBuildMode types.Bool `tfsdk:"remote_repo_build_mode"`
72+
SSLCertBase64 types.String `tfsdk:"ssl_cert_base64"`
73+
Verbose types.Bool `tfsdk:"verbose"`
74+
WorkspaceFolder types.String `tfsdk:"workspace_folder"`
7475
// Computed "outputs".
7576
Env types.List `tfsdk:"env"`
7677
EnvMap types.Map `tfsdk:"env_map"`
@@ -186,6 +187,11 @@ func (r *CachedImageResource) Schema(ctx context.Context, req resource.SchemaReq
186187
MarkdownDescription: "(Envbuilder option) Path to an SSH private key to be used for Git authentication.",
187188
Optional: true,
188189
},
190+
"git_ssh_private_key_base64": schema.StringAttribute{
191+
MarkdownDescription: "(Envbuilder option) Base64 encoded SSH private key to be used for Git authentication.",
192+
Optional: true,
193+
Sensitive: true,
194+
},
189195
"git_username": schema.StringAttribute{
190196
MarkdownDescription: "(Envbuilder option) The username to use for Git authentication. This is optional.",
191197
Optional: true,

internal/provider/helpers.go

+10
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ func optionsFromDataModel(data CachedImageResourceModel) (eboptions.Options, dia
102102
opts.GitSSHPrivateKeyPath = data.GitSSHPrivateKeyPath.ValueString()
103103
}
104104

105+
if !data.GitSSHPrivateKeyBase64.IsNull() {
106+
providerOpts["ENVBUILDER_GIT_SSH_PRIVATE_KEY_BASE64"] = true
107+
opts.GitSSHPrivateKeyBase64 = data.GitSSHPrivateKeyBase64.ValueString()
108+
}
109+
105110
if !data.GitUsername.IsNull() {
106111
providerOpts["ENVBUILDER_GIT_USERNAME"] = true
107112
opts.GitUsername = data.GitUsername.ValueString()
@@ -151,6 +156,11 @@ func optionsFromDataModel(data CachedImageResourceModel) (eboptions.Options, dia
151156
}
152157
diags = append(diags, overrideOptionsFromExtraEnv(&opts, extraEnv, providerOpts)...)
153158

159+
if opts.GitSSHPrivateKeyPath != "" && opts.GitSSHPrivateKeyBase64 != "" {
160+
diags.AddError("Cannot set more than one git ssh private key option",
161+
"Both ENVBUILDER_GIT_SSH_PRIVATE_KEY_PATH and ENVBUILDER_GIT_SSH_PRIVATE_KEY_BASE64 have been set.")
162+
}
163+
154164
return opts, diags
155165
}
156166

internal/provider/provider_internal_test.go

+53
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,59 @@ func Test_optionsFromDataModel(t *testing.T) {
211211
},
212212
expectNumErrorDiags: 2,
213213
},
214+
{
215+
name: "errors when git ssh private key path and base64 are set",
216+
data: CachedImageResourceModel{
217+
BuilderImage: basetypes.NewStringValue("envbuilder:latest"),
218+
CacheRepo: basetypes.NewStringValue("localhost:5000/cache"),
219+
GitURL: basetypes.NewStringValue("[email protected]/devcontainer.git"),
220+
GitSSHPrivateKeyPath: basetypes.NewStringValue("/tmp/id_rsa"),
221+
GitSSHPrivateKeyBase64: basetypes.NewStringValue("cHJpdmF0ZUtleQo="),
222+
},
223+
expectOpts: eboptions.Options{
224+
CacheRepo: "localhost:5000/cache",
225+
GitURL: "[email protected]/devcontainer.git",
226+
RemoteRepoBuildMode: true,
227+
GitSSHPrivateKeyPath: "/tmp/id_rsa",
228+
GitSSHPrivateKeyBase64: "cHJpdmF0ZUtleQo=",
229+
},
230+
expectNumErrorDiags: 1,
231+
},
232+
{
233+
name: "extra_env override errors when git ssh private key path and base64 are set",
234+
data: CachedImageResourceModel{
235+
BuilderImage: basetypes.NewStringValue("envbuilder:latest"),
236+
CacheRepo: basetypes.NewStringValue("localhost:5000/cache"),
237+
GitURL: basetypes.NewStringValue("[email protected]/devcontainer.git"),
238+
GitSSHPrivateKeyBase64: basetypes.NewStringValue("cHJpdmF0ZUtleQo="),
239+
ExtraEnv: extraEnvMap(t,
240+
"ENVBUILDER_GIT_SSH_PRIVATE_KEY_PATH", "/tmp/id_rsa",
241+
),
242+
},
243+
expectOpts: eboptions.Options{
244+
CacheRepo: "localhost:5000/cache",
245+
GitURL: "[email protected]/devcontainer.git",
246+
RemoteRepoBuildMode: true,
247+
GitSSHPrivateKeyPath: "/tmp/id_rsa",
248+
GitSSHPrivateKeyBase64: "cHJpdmF0ZUtleQo=",
249+
},
250+
expectNumErrorDiags: 1,
251+
},
252+
{
253+
name: "required only with base64 ssh key",
254+
data: CachedImageResourceModel{
255+
BuilderImage: basetypes.NewStringValue("envbuilder:latest"),
256+
CacheRepo: basetypes.NewStringValue("localhost:5000/cache"),
257+
GitURL: basetypes.NewStringValue("[email protected]/devcontainer.git"),
258+
GitSSHPrivateKeyBase64: basetypes.NewStringValue("cHJpdmF0ZUtleQo="),
259+
},
260+
expectOpts: eboptions.Options{
261+
CacheRepo: "localhost:5000/cache",
262+
GitURL: "[email protected]/devcontainer.git",
263+
RemoteRepoBuildMode: true,
264+
GitSSHPrivateKeyBase64: "cHJpdmF0ZUtleQo=",
265+
},
266+
},
214267
} {
215268
t.Run(tc.name, func(t *testing.T) {
216269
t.Parallel()

0 commit comments

Comments
 (0)