Skip to content

Commit 653e884

Browse files
authored
nixcache: configure auth with devbox cache configure (#1961)
Add a hidden `devbox cache configure` command that sets up Nix so it can authenticate with a private Devbox cache. This is a first step. Ultimately, we'd like to do this configuration automatically before building. We just need to make sure we don't re-prompt the user for sudo or slow down commands like `devbox run` or `devbox shell`. Configuring auth goes as follows: 1. Check to see if the Nix daemon is running. If it isn't, we don't need to do anything. 2. Otherwise, we check to see if `~root/.aws/config` exists. If it does, we assume that we've already configured the root user's AWS credentials. This won't handle situations where the user already has a root AWS config and can be improved. 3. If the AWS config doesn't exist, prompt the user to escalate to root. If they say yes, relaunch `devbox cache configure`. 4. The new devbox process running as root writes an AWS config file that tells the AWS CLI/SDKs to authenticate by running `devbox cache credentials`. Note that we need to use the default AWS profile. There's a bug in Nix where non-default profiles (specified in the S3 URI with ?profile=devbox) don't use the default credential chain. If this gets fixed, we should use a separate profile so that we don't interfere with any AWS options set by the user (although hopefully this is rare for root).
1 parent ef831bb commit 653e884

File tree

6 files changed

+276
-106
lines changed

6 files changed

+276
-106
lines changed

go.mod

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ require (
1010
github.com/aws/aws-sdk-go-v2/config v1.27.7
1111
github.com/aws/aws-sdk-go-v2/credentials v1.17.7
1212
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9
13-
github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.23.4
1413
github.com/aws/aws-sdk-go-v2/service/s3 v1.53.0
1514
github.com/aws/aws-sdk-go-v2/service/sts v1.28.4
1615
github.com/bmatcuk/doublestar/v4 v4.6.1
@@ -40,7 +39,7 @@ require (
4039
github.com/wk8/go-ordered-map/v2 v2.1.8
4140
github.com/zealic/go2node v0.1.0
4241
go.jetpack.io/envsec v0.0.16-0.20240329013200-4174c0acdb00
43-
go.jetpack.io/pkg v0.0.0-20240404001923-7b42192bf9a5
42+
go.jetpack.io/pkg v0.0.0-20240405214046-034a6476e201
4443
go.jetpack.io/typeid v1.0.0
4544
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
4645
golang.org/x/mod v0.16.0

go.sum

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7
6262
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
6363
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.4 h1:SIkD6T4zGQ+1YIit22wi37CGNkrE7mXV1vNA5VpI3TI=
6464
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.4/go.mod h1:XfeqbsG0HNedNs0GT+ju4Bs+pFAwsrlzcRdMvdNVf5s=
65-
github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.23.4 h1:KuN2GQBLzac3PdhsVBt7n11jKfRsXg0OZSuuizF+yNw=
66-
github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.23.4/go.mod h1:OnFArLhSkVvZjmlx3wiYir/O44gpEerCXPJbK+LQBSE=
6765
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
6866
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
6967
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.6 h1:NkHCgg0Ck86c5PTOzBZ0JRccI51suJDg5lgFtxBu1ek=
@@ -365,8 +363,8 @@ github.com/zealic/go2node v0.1.0 h1:ofxpve08cmLJBwFdI0lPCk9jfwGWOSD+s6216x0oAaA=
365363
github.com/zealic/go2node v0.1.0/go.mod h1:GrkFr+HctXwP7vzcU9RsgtAeJjTQ6Ud0IPCQAqpTfBg=
366364
go.jetpack.io/envsec v0.0.16-0.20240329013200-4174c0acdb00 h1:Kb+OlWOntAq+1nF+01ntqnQEqSJkFmLLS0RX5sl5zak=
367365
go.jetpack.io/envsec v0.0.16-0.20240329013200-4174c0acdb00/go.mod h1:dVG2n8fBAGpQczW8yk/6wuXb9uEhzaJF7wGXkGLRRCU=
368-
go.jetpack.io/pkg v0.0.0-20240404001923-7b42192bf9a5 h1:uFFlceGNlxqrKA/1umrBvNLTTBNkBU306Uqq1O27agM=
369-
go.jetpack.io/pkg v0.0.0-20240404001923-7b42192bf9a5/go.mod h1:gtmpVShXMEcZPBFZHswB3oCPYXobeR41b9CMybAjQYw=
366+
go.jetpack.io/pkg v0.0.0-20240405214046-034a6476e201 h1:59icpq6Y6uqnyG+IVijjGvLnL4U3syjFkq2ILnsC30Q=
367+
go.jetpack.io/pkg v0.0.0-20240405214046-034a6476e201/go.mod h1:gtmpVShXMEcZPBFZHswB3oCPYXobeR41b9CMybAjQYw=
370368
go.jetpack.io/typeid v1.0.0 h1:8gQ+iYGdyiQ0Pr40ydSB/PzMOIwlXX5DTojp1CBeSPQ=
371369
go.jetpack.io/typeid v1.0.0/go.mod h1:+UPEaECUgFxgAjFPn5Yf9eO/3ft/3xZ98Eahv9JW/GQ=
372370
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=

internal/boxcli/cache.go

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package boxcli
55

66
import (
77
"encoding/json"
8+
"os/user"
89

910
"github.com/MakeNowJust/heredoc/v2"
1011
"github.com/pkg/errors"
@@ -33,9 +34,9 @@ func cacheCmd() *cobra.Command {
3334
Short: "upload specified or nix packages in current project to cache",
3435
Long: heredoc.Doc(`
3536
Upload specified nix installable or nix packages in current project to cache.
36-
If [installable] is provided, only that installable will be uploaded.
37+
If [installable] is provided, only that installable will be uploaded.
3738
Otherwise, all packages in the project will be uploaded.
38-
To upload to specific cache, use --to flag. Otherwise, a cache from
39+
To upload to specific cache, use --to flag. Otherwise, a cache from
3940
the cache provider will be used, if available.
4041
`),
4142
Args: cobra.MaximumNArgs(1),
@@ -61,41 +62,49 @@ func cacheCmd() *cobra.Command {
6162
&flags.to, "to", "", "URI of the cache to copy to")
6263

6364
cacheCommand.AddCommand(uploadCommand)
65+
cacheCommand.AddCommand(cacheConfigureCmd())
6466
cacheCommand.AddCommand(cacheCredentialsCmd())
6567
cacheCommand.Hidden = true
6668

6769
return cacheCommand
6870
}
6971

72+
func cacheConfigureCmd() *cobra.Command {
73+
username := ""
74+
cmd := &cobra.Command{
75+
Use: "configure",
76+
Short: "Configure Nix to use the Devbox cache as a substituter",
77+
Hidden: true,
78+
Args: cobra.MaximumNArgs(0),
79+
RunE: func(cmd *cobra.Command, args []string) error {
80+
if username == "" {
81+
u, _ := user.Current()
82+
username = u.Username
83+
}
84+
return nixcache.Get().ConfigureAWS(cmd.Context(), username)
85+
},
86+
}
87+
cmd.Flags().StringVar(&username, "user", "", "")
88+
return cmd
89+
}
90+
7091
func cacheCredentialsCmd() *cobra.Command {
7192
return &cobra.Command{
7293
Use: "credentials",
7394
Short: "Output S3 cache credentials",
7495
Hidden: true,
7596
Args: cobra.ExactArgs(0),
7697
RunE: func(cmd *cobra.Command, args []string) error {
77-
cfg, err := nixcache.Get().Config(cmd.Context())
98+
creds, err := nixcache.Get().Credentials(cmd.Context())
7899
if err != nil {
79100
return err
80101
}
81-
82-
creds := struct {
83-
Version int `json:"Version"`
84-
AccessKeyID string `json:"AccessKeyId"`
85-
SecretAccessKey string `json:"SecretAccessKey"`
86-
SessionToken string `json:"SessionToken"`
87-
}{
88-
Version: 1,
89-
AccessKeyID: *cfg.Credentials.AccessKeyId,
90-
SecretAccessKey: *cfg.Credentials.SecretKey,
91-
SessionToken: *cfg.Credentials.SessionToken,
92-
}
93102
out, err := json.Marshal(creds)
94103
if err != nil {
95104
return err
96105
}
97-
_, _ = cmd.OutOrStdout().Write(out)
98-
return nil
106+
_, err = cmd.OutOrStdout().Write(out)
107+
return err
99108
},
100109
}
101110
}

internal/devbox/cache.go

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"io"
66

7+
"go.jetpack.io/devbox/internal/boxcli/usererr"
78
"go.jetpack.io/devbox/internal/devbox/providers/nixcache"
89
"go.jetpack.io/devbox/internal/nix"
910
)
@@ -12,38 +13,47 @@ func (d *Devbox) UploadProjectToCache(
1213
ctx context.Context,
1314
cacheURI string,
1415
) error {
15-
var err error
16-
cacheConfig := nixcache.NixCacheConfig{URI: cacheURI}
17-
if cacheConfig.URI == "" {
18-
cacheConfig, err = d.providers.NixCache.Config(ctx)
16+
if cacheURI == "" {
17+
var err error
18+
cacheURI, err = d.providers.NixCache.URI(ctx)
1919
if err != nil {
2020
return err
2121
}
22+
if cacheURI == "" {
23+
return usererr.New("Your account's organization doesn't have a Nix cache.")
24+
}
25+
}
26+
27+
creds, err := d.providers.NixCache.Credentials(ctx)
28+
if err != nil {
29+
return err
2230
}
2331
profilePath, err := d.profilePath()
2432
if err != nil {
2533
return err
2634
}
27-
28-
return nix.CopyInstallableToCache(
29-
ctx,
30-
d.stderr, cacheConfig.URI, profilePath, cacheConfig.CredentialsEnvVars())
35+
return nix.CopyInstallableToCache(ctx, d.stderr, cacheURI, profilePath, creds.Env())
3136
}
3237

3338
func UploadInstallableToCache(
3439
ctx context.Context,
3540
stderr io.Writer,
3641
cacheURI, installable string,
3742
) error {
38-
var err error
39-
cacheConfig := nixcache.NixCacheConfig{URI: cacheURI}
40-
if cacheConfig.URI == "" {
41-
cacheConfig, err = nixcache.Get().Config(ctx)
43+
if cacheURI == "" {
44+
var err error
45+
cacheURI, err = nixcache.Get().URI(ctx)
4246
if err != nil {
4347
return err
4448
}
49+
if cacheURI == "" {
50+
return usererr.New("Your account's organization doesn't have a Nix cache.")
51+
}
52+
}
53+
54+
creds, err := nixcache.Get().Credentials(ctx)
55+
if err != nil {
56+
return err
4557
}
46-
return nix.CopyInstallableToCache(
47-
ctx,
48-
stderr, cacheConfig.URI, installable, cacheConfig.CredentialsEnvVars())
58+
return nix.CopyInstallableToCache(ctx, stderr, cacheURI, installable, creds.Env())
4959
}

internal/devbox/packages.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -445,19 +445,19 @@ func (d *Devbox) installNixPackagesToStore(ctx context.Context, mode installMode
445445
flags = append(flags, "--refresh")
446446
}
447447

448-
nixCacheConfig, err := d.providers.NixCache.Config(ctx)
449-
if err != nil {
450-
return err
448+
args := &nix.BuildArgs{
449+
AllowInsecure: pkg.HasAllowInsecure(),
450+
Flags: flags,
451+
Writer: d.stderr,
451452
}
452-
453-
for _, installable := range installables {
454-
args := &nix.BuildArgs{
455-
AllowInsecure: pkg.HasAllowInsecure(),
456-
Env: nixCacheConfig.CredentialsEnvVars(),
457-
ExtraSubstituter: nixCacheConfig.URI,
458-
Flags: flags,
459-
Writer: d.stderr,
453+
args.ExtraSubstituter, err = d.providers.NixCache.URI(ctx)
454+
if err == nil {
455+
creds, err := d.providers.NixCache.Credentials(ctx)
456+
if err == nil {
457+
args.Env = creds.Env()
460458
}
459+
}
460+
for _, installable := range installables {
461461
err = nix.Build(ctx, args, installable)
462462
if err != nil {
463463
fmt.Fprintf(d.stderr, "%s: ", stepMsg)

0 commit comments

Comments
 (0)