diff --git a/go.mod b/go.mod index f8fe4132d0d..763738dd9d9 100644 --- a/go.mod +++ b/go.mod @@ -6,11 +6,12 @@ require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/MakeNowJust/heredoc/v2 v2.0.1 github.com/alessio/shellescape v1.4.2 - github.com/aws/aws-sdk-go-v2 v1.25.3 + github.com/aws/aws-sdk-go-v2 v1.26.0 github.com/aws/aws-sdk-go-v2/config v1.27.7 github.com/aws/aws-sdk-go-v2/credentials v1.17.7 github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 - github.com/aws/aws-sdk-go-v2/service/s3 v1.51.4 + github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.23.4 + github.com/aws/aws-sdk-go-v2/service/s3 v1.53.0 github.com/aws/aws-sdk-go-v2/service/sts v1.28.4 github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/briandowns/spinner v1.23.0 @@ -38,8 +39,8 @@ require ( github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a github.com/wk8/go-ordered-map/v2 v2.1.8 github.com/zealic/go2node v0.1.0 - go.jetpack.io/envsec v0.0.16-0.20240214025624-d233cf877eec - go.jetpack.io/pkg v0.0.0-20240213204231-ec96be3d78fb + go.jetpack.io/envsec v0.0.16-0.20240329013200-4174c0acdb00 + go.jetpack.io/pkg v0.0.0-20240329001056-e451f5c5e234 golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 golang.org/x/mod v0.16.0 golang.org/x/sync v0.6.0 @@ -49,21 +50,21 @@ require ( ) require ( - connectrpc.com/connect v1.15.0 // indirect + connectrpc.com/connect v1.16.0 // indirect github.com/InVisionApp/go-health/v2 v2.1.4 // indirect github.com/InVisionApp/go-logger v1.0.1 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect github.com/andybalholm/brotli v1.1.0 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.4 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.4 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.20.2 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.2 // indirect github.com/aws/smithy-go v1.20.1 // indirect diff --git a/go.sum b/go.sum index 13fcd1bffc1..3c0112367cf 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2k cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -connectrpc.com/connect v1.15.0 h1:lFdeCbZrVVDydAqwr4xGV2y+ULn+0Z73s5JBj2LikWo= -connectrpc.com/connect v1.15.0/go.mod h1:bQmjpDY8xItMnttnurVgOkHUBMRT9cpsNi2O4AjKhmA= +connectrpc.com/connect v1.16.0 h1:rdtfQjZ0OyFkWPTegBNcH7cwquGAN1WzyJy80oFNibg= +connectrpc.com/connect v1.16.0/go.mod h1:XpZAduBQUySsb4/KO5JffORVkDI4B6/EYPi7N8xpNZw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= @@ -42,8 +42,8 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1 github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/arduino/go-paths-helper v1.2.0 h1:qDW93PR5IZUN/jzO4rCtexiwF8P4OIcOmcSgAYLZfY4= github.com/arduino/go-paths-helper v1.2.0/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck= -github.com/aws/aws-sdk-go-v2 v1.25.3 h1:xYiLpZTQs1mzvz5PaI6uR0Wh57ippuEthxS4iK5v0n0= -github.com/aws/aws-sdk-go-v2 v1.25.3/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I= +github.com/aws/aws-sdk-go-v2 v1.26.0 h1:/Ce4OCiM3EkpW7Y+xUnfAFpchU78K7/Ug01sZni9PgA= +github.com/aws/aws-sdk-go-v2 v1.26.0/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1/go.mod h1:sxpLb+nZk7tIfCWChfd+h4QwHNUR57d8hA1cleTkjJo= github.com/aws/aws-sdk-go-v2/config v1.27.7 h1:JSfb5nOQF01iOgxFI5OIKWwDiEXWTyTgg1Mm1mHi0A4= @@ -54,24 +54,26 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3 h1:p+y7FvkK2dxS+FEwRIDHDe/ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3/go.mod h1:/fYB+FZbDlwlAiynK9KDXlzZl3ANI9JkD0Uhz5FjNT4= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9 h1:vXY/Hq1XdxHBIYgBUmug/AbMyIe1AKulPYS2/VE1X70= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.9/go.mod h1:GyJJTZoHVuENM4TeJEl5Ffs4W9m19u+4wKJcDi/GZ4A= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3 h1:ifbIbHZyGl1alsAhPIYsHOg5MuApgqOvVeI8wIugXfs= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3/go.mod h1:oQZXg3c6SNeY6OZrDY+xHcF4VGIEoNotX2B4PrDeoJI= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3 h1:Qvodo9gHG9F3E8SfYOspPeBt0bjSbsevK8WhRAUHcoY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3/go.mod h1:vCKrdLXtybdf/uQd/YfVR2r5pcbNuEYKzMQpcxmeSJw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4 h1:0ScVK/4qZ8CIW0k8jOeFVsyS/sAiXpYxRBLolMkuLQM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4/go.mod h1:84KyjNZdHC6QZW08nfHI6yZgPd+qRgaWcYsyLUo3QY8= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4 h1:sHmMWWX5E7guWEFQ9SVo6A3S4xpPrWnd77a6y4WM6PU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4/go.mod h1:WjpDrhWisWOIoS9n3nk67A3Ll1vfULJ9Kq6h29HTD48= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.3 h1:mDnFOE2sVkyphMWtTH+stv0eW3k0OTx94K63xpxHty4= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.3/go.mod h1:V8MuRVcCRt5h1S+Fwu8KbC7l/gBGo3yBAyUbJM2IJOk= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.4 h1:SIkD6T4zGQ+1YIit22wi37CGNkrE7mXV1vNA5VpI3TI= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.4/go.mod h1:XfeqbsG0HNedNs0GT+ju4Bs+pFAwsrlzcRdMvdNVf5s= +github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.23.4 h1:KuN2GQBLzac3PdhsVBt7n11jKfRsXg0OZSuuizF+yNw= +github.com/aws/aws-sdk-go-v2/service/cognitoidentity v1.23.4/go.mod h1:OnFArLhSkVvZjmlx3wiYir/O44gpEerCXPJbK+LQBSE= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.5 h1:mbWNpfRUTT6bnacmvOTKXZjR/HycibdWzNpfbrbLDIs= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.5/go.mod h1:FCOPWGjsshkkICJIn9hq9xr6dLKtyaWpuUojiN3W1/8= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5 h1:K/NXvIftOlX+oGgWGIa3jDyYLDNsdVhsjHmsBH2GLAQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5/go.mod h1:cl9HGLV66EnCmMNzq4sYOti+/xo8w34CsgzVtm2GgsY= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.3 h1:4t+QEX7BsXz98W8W1lNvMAG+NX8qHz2CjLBxQKku40g= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.3/go.mod h1:oFcjjUq5Hm09N9rpxTdeMeLeQcxS7mIkBkL8qUKng+A= -github.com/aws/aws-sdk-go-v2/service/s3 v1.51.4 h1:lW5xUzOPGAMY7HPuNF4FdyBwRc3UJ/e8KsapbesVeNU= -github.com/aws/aws-sdk-go-v2/service/s3 v1.51.4/go.mod h1:MGTaf3x/+z7ZGugCGvepnx2DS6+caCYYqKhzVoLNYPk= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.6 h1:NkHCgg0Ck86c5PTOzBZ0JRccI51suJDg5lgFtxBu1ek= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.6/go.mod h1:mjTpxjC8v4SeINTngrnKFgm2QUi+Jm+etTbCxh8W4uU= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 h1:b+E7zIUHMmcB4Dckjpkapoy47W6C9QBv/zoUP+Hn8Kc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6/go.mod h1:S2fNV0rxrP78NhPbCZeQgY8H9jdDMeGtwcfZIRxzBqU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.4 h1:uDj2K47EM1reAYU9jVlQ1M5YENI1u6a/TxJpf6AeOLA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.4/go.mod h1:XKCODf4RKHppc96c2EZBGV/oCUC7OClxAo2MEyg4pIk= +github.com/aws/aws-sdk-go-v2/service/s3 v1.53.0 h1:r3o2YsgW9zRcIP3Q0WCmttFVhTuugeKIvT5z9xDspc0= +github.com/aws/aws-sdk-go-v2/service/s3 v1.53.0/go.mod h1:w2E4f8PUfNtyjfL6Iu+mWI96FGttE03z3UdNcUEC4tA= github.com/aws/aws-sdk-go-v2/service/sso v1.20.2 h1:XOPfar83RIRPEzfihnp+U6udOveKZJvPQ76SKWrLRHc= github.com/aws/aws-sdk-go-v2/service/sso v1.20.2/go.mod h1:Vv9Xyk1KMHXrR3vNQe8W5LMFdTjSeWk0gBZBzvf3Qa0= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.2 h1:pi0Skl6mNl2w8qWZXcdOyg197Zsf4G97U7Sso9JXGZE= @@ -361,10 +363,14 @@ github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBU github.com/zaffka/mongodb-boltdb-mock v0.0.0-20221014194232-b4bb03fbe3a0/go.mod h1:GsDD1qsG+86MeeCG7ndi6Ei3iGthKL3wQ7PTFigDfNY= github.com/zealic/go2node v0.1.0 h1:ofxpve08cmLJBwFdI0lPCk9jfwGWOSD+s6216x0oAaA= github.com/zealic/go2node v0.1.0/go.mod h1:GrkFr+HctXwP7vzcU9RsgtAeJjTQ6Ud0IPCQAqpTfBg= -go.jetpack.io/envsec v0.0.16-0.20240214025624-d233cf877eec h1:IvdOF1C8tAxvKEauWBd/4IWXZfeyXh5vmcfTrcTBPvQ= -go.jetpack.io/envsec v0.0.16-0.20240214025624-d233cf877eec/go.mod h1:koTmI1q2QKqtxaX4P/7r5ygODwgJQ56FKoKRfzpZ0bM= -go.jetpack.io/pkg v0.0.0-20240213204231-ec96be3d78fb h1:ELaZEV3BL+/GDfPxWPXt6ODNig/VlywWhfAC4P8EG5A= -go.jetpack.io/pkg v0.0.0-20240213204231-ec96be3d78fb/go.mod h1:kGUL8aZ7ddvoGro0AQxXos9GKn5Qw0J18qW7d5FP4Ws= +go.jetpack.io/envsec v0.0.16-0.20240327051701-1c56cf3690d7 h1:f+EANkek7CaHK6LS9RIm9rbOt2WrZYyYFTsXGKUdMgc= +go.jetpack.io/envsec v0.0.16-0.20240327051701-1c56cf3690d7/go.mod h1:Z4tKIpAkdW4tpNUlToVLg7LZFl688GxWae02m3w//G0= +go.jetpack.io/envsec v0.0.16-0.20240329013200-4174c0acdb00 h1:Kb+OlWOntAq+1nF+01ntqnQEqSJkFmLLS0RX5sl5zak= +go.jetpack.io/envsec v0.0.16-0.20240329013200-4174c0acdb00/go.mod h1:dVG2n8fBAGpQczW8yk/6wuXb9uEhzaJF7wGXkGLRRCU= +go.jetpack.io/pkg v0.0.0-20240327051701-89e2d24bc65e h1:JuyexYMVBsXwMrnmcCYVEOP9+Mrtvo0mAHSGeWdDUS0= +go.jetpack.io/pkg v0.0.0-20240327051701-89e2d24bc65e/go.mod h1:vpIQT+m8iHO11v6bgMMG6iWfbGE2vxvLr9k7hLb4OeU= +go.jetpack.io/pkg v0.0.0-20240329001056-e451f5c5e234 h1:MHZNJeQQwxqwVJhaCKtHAkCXrv3sWQkJoVf0i8Pf1Ro= +go.jetpack.io/pkg v0.0.0-20240329001056-e451f5c5e234/go.mod h1:vpIQT+m8iHO11v6bgMMG6iWfbGE2vxvLr9k7hLb4OeU= go.jetpack.io/typeid v1.0.0 h1:8gQ+iYGdyiQ0Pr40ydSB/PzMOIwlXX5DTojp1CBeSPQ= go.jetpack.io/typeid v1.0.0/go.mod h1:+UPEaECUgFxgAjFPn5Yf9eO/3ft/3xZ98Eahv9JW/GQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= diff --git a/internal/boxcli/auth.go b/internal/boxcli/auth.go index c3c7c65738a..c6089eb193a 100644 --- a/internal/boxcli/auth.go +++ b/internal/boxcli/auth.go @@ -4,21 +4,15 @@ package boxcli import ( - "context" "fmt" "os" "github.com/spf13/cobra" - "go.jetpack.io/devbox/internal/build" "go.jetpack.io/devbox/internal/devbox" "go.jetpack.io/devbox/internal/devbox/devopt" - "go.jetpack.io/pkg/auth" - "go.jetpack.io/pkg/auth/session" + "go.jetpack.io/devbox/internal/devbox/providers/identity" ) -// This matches default scopes for envsec. TODO: export this in envsec. -var scopes = []string{"openid", "offline_access", "email", "profile"} - func authCmd() *cobra.Command { cmd := &cobra.Command{ Use: "auth", @@ -38,7 +32,7 @@ func loginCmd() *cobra.Command { Short: "Login to devbox", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { - c, err := newAuthClient() + c, err := identity.Get().AuthClient() if err != nil { return err } @@ -60,7 +54,7 @@ func logoutCmd() *cobra.Command { Short: "Logout from devbox", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { - c, err := newAuthClient() + c, err := identity.Get().AuthClient() if err != nil { return err } @@ -108,20 +102,3 @@ func whoAmICmd() *cobra.Command { return cmd } - -func genSession(ctx context.Context) (*session.Token, error) { - c, err := newAuthClient() - if err != nil { - return nil, err - } - return c.GetSession(ctx) -} - -func newAuthClient() (*auth.Client, error) { - return auth.NewClient( - build.Issuer(), - build.ClientID(), - scopes, - build.SuccessRedirect(), - ) -} diff --git a/internal/boxcli/pull.go b/internal/boxcli/pull.go index 88ab12546b5..789e66c42cc 100644 --- a/internal/boxcli/pull.go +++ b/internal/boxcli/pull.go @@ -15,6 +15,7 @@ import ( "go.jetpack.io/devbox/internal/boxcli/usererr" "go.jetpack.io/devbox/internal/devbox" "go.jetpack.io/devbox/internal/devbox/devopt" + "go.jetpack.io/devbox/internal/devbox/providers/identity" "go.jetpack.io/devbox/internal/goutil" "go.jetpack.io/devbox/internal/pullbox/s3" "go.jetpack.io/pkg/auth" @@ -64,7 +65,7 @@ func pullCmdFunc(cmd *cobra.Command, url string, flags *pullCmdFlags) error { } var creds devopt.Credentials - t, err := genSession(cmd.Context()) + t, err := identity.Get().GenSession(cmd.Context()) if err != nil && !errors.Is(err, auth.ErrNotLoggedIn) { return errors.WithStack(err) } else if t != nil && err == nil { diff --git a/internal/boxcli/push.go b/internal/boxcli/push.go index 5ea4794e2f8..776626346ec 100644 --- a/internal/boxcli/push.go +++ b/internal/boxcli/push.go @@ -10,6 +10,7 @@ import ( "go.jetpack.io/devbox/internal/devbox" "go.jetpack.io/devbox/internal/devbox/devopt" + "go.jetpack.io/devbox/internal/devbox/providers/identity" "go.jetpack.io/devbox/internal/goutil" ) @@ -43,7 +44,7 @@ func pushCmdFunc(cmd *cobra.Command, url string, flags pushCmdFlags) error { if err != nil { return errors.WithStack(err) } - t, err := genSession(cmd.Context()) + t, err := identity.Get().GenSession(cmd.Context()) var creds devopt.Credentials if err != nil && !errors.Is(err, auth.ErrNotLoggedIn) { return errors.WithStack(err) diff --git a/internal/build/build.go b/internal/build/build.go index 8f07fc3d090..e5bb89b8da5 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -87,3 +87,7 @@ func SuccessRedirect() string { } return "https://auth.jetpack.io/account/login/success" } + +func Audience() []string { + return []string{"https://api.jetpack.io"} +} diff --git a/internal/devbox/bincache/bincache.go b/internal/devbox/bincache/bincache.go deleted file mode 100644 index 7d08aec9a76..00000000000 --- a/internal/devbox/bincache/bincache.go +++ /dev/null @@ -1,25 +0,0 @@ -package bincache - -import "os" - -// ExtraSubstituter returns the URI of the extra substituter to use. -// a substituter is a bin cache URI that nix can use to fetch pre-built -// binaries from. -func ExtraSubstituter() (string, error) { - if err := ensureTrustedUser(); err != nil { - return "", err - } - - // TODO: if user is logged in (or if we have token we can refresh) - // then we try to fetch the bincache URI from the API. - - // DEVBOX_NIX_BINCACHE_URI seems like a friendlier name than "substituter" - return os.Getenv("DEVBOX_NIX_BINCACHE_URI"), nil -} - -func ensureTrustedUser() error { - // TODO: we need to ensure that the user can actually use the extra - // substituter. If the user did a root install, then we need to add - // the extra substituter to the nix.conf file and restart the daemon. - return nil -} diff --git a/internal/devbox/cache.go b/internal/devbox/cache.go index fa09ef5a413..4c4d8d474a5 100644 --- a/internal/devbox/cache.go +++ b/internal/devbox/cache.go @@ -3,14 +3,23 @@ package devbox import ( "context" + "go.jetpack.io/devbox/internal/devbox/providers/nixcache" "go.jetpack.io/devbox/internal/nix" ) func (d *Devbox) CacheCopy(ctx context.Context, cacheURI string) error { + var err error + cacheConfig := nixcache.NixCacheConfig{URI: cacheURI} + if cacheConfig.URI == "" { + cacheConfig, err = d.providers.NixCache.Config(ctx) + if err != nil { + return err + } + } profilePath, err := d.profilePath() if err != nil { return err } - return nix.CopyInstallableToCache(ctx, d.stderr, cacheURI, profilePath) + return nix.CopyInstallableToCache(ctx, d.stderr, cacheConfig.URI, profilePath) } diff --git a/internal/devbox/devbox.go b/internal/devbox/devbox.go index 4ddbbf1a933..72b9c67a2e4 100644 --- a/internal/devbox/devbox.go +++ b/internal/devbox/devbox.go @@ -27,6 +27,7 @@ import ( "go.jetpack.io/devbox/internal/cachehash" "go.jetpack.io/devbox/internal/devbox/envpath" "go.jetpack.io/devbox/internal/devbox/generate" + "go.jetpack.io/devbox/internal/devbox/providers" "go.jetpack.io/devbox/internal/devpkg" "go.jetpack.io/devbox/internal/devpkg/pkgtype" "go.jetpack.io/devbox/internal/searcher" @@ -65,6 +66,7 @@ type Devbox struct { lockfile *lock.File nix nix.Nixer projectDir string + providers providers.Providers pluginManager *plugin.Manager preservePathStack bool pure bool diff --git a/internal/devbox/packages.go b/internal/devbox/packages.go index e69a00bae00..a92dbb88ea9 100644 --- a/internal/devbox/packages.go +++ b/internal/devbox/packages.go @@ -17,7 +17,6 @@ import ( "github.com/fatih/color" "github.com/pkg/errors" "github.com/samber/lo" - "go.jetpack.io/devbox/internal/devbox/bincache" "go.jetpack.io/devbox/internal/devbox/devopt" "go.jetpack.io/devbox/internal/devconfig" "go.jetpack.io/devbox/internal/devpkg" @@ -446,7 +445,7 @@ func (d *Devbox) installNixPackagesToStore(ctx context.Context, mode installMode flags = append(flags, "--refresh") } - extraSubstituter, err := bincache.ExtraSubstituter() + nixCacheConfig, err := d.providers.NixCache.Config(ctx) if err != nil { return err } @@ -454,9 +453,10 @@ func (d *Devbox) installNixPackagesToStore(ctx context.Context, mode installMode for _, installable := range installables { args := &nix.BuildArgs{ AllowInsecure: pkg.HasAllowInsecure(), + Env: nixCacheConfig.CredentialsEnvVars(), + ExtraSubstituter: nixCacheConfig.URI, Flags: flags, Writer: d.stderr, - ExtraSubstituter: extraSubstituter, } err = nix.Build(ctx, args, installable) if err != nil { diff --git a/internal/devbox/providers/identity/identity.go b/internal/devbox/providers/identity/identity.go new file mode 100644 index 00000000000..104f04fcd55 --- /dev/null +++ b/internal/devbox/providers/identity/identity.go @@ -0,0 +1,37 @@ +package identity + +import ( + "context" + + "go.jetpack.io/devbox/internal/build" + "go.jetpack.io/pkg/auth" + "go.jetpack.io/pkg/auth/session" +) + +var scopes = []string{"openid", "offline_access", "email", "profile"} + +type Provider struct{} + +var singleton *Provider = &Provider{} + +func Get() *Provider { + return singleton +} + +func (p *Provider) GenSession(ctx context.Context) (*session.Token, error) { + c, err := p.AuthClient() + if err != nil { + return nil, err + } + return c.GetSession(ctx) +} + +func (p *Provider) AuthClient() (*auth.Client, error) { + return auth.NewClient( + build.Issuer(), + build.ClientID(), + scopes, + build.SuccessRedirect(), + build.Audience(), + ) +} diff --git a/internal/devbox/providers/nixcache/nixcache.go b/internal/devbox/providers/nixcache/nixcache.go new file mode 100644 index 00000000000..0c0941e2381 --- /dev/null +++ b/internal/devbox/providers/nixcache/nixcache.go @@ -0,0 +1,99 @@ +package nixcache + +import ( + "context" + "errors" + "os" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/cognitoidentity/types" + "go.jetpack.io/devbox/internal/build" + "go.jetpack.io/devbox/internal/devbox/providers/identity" + "go.jetpack.io/devbox/internal/nix" + "go.jetpack.io/devbox/internal/ux" + "go.jetpack.io/pkg/api" + "go.jetpack.io/pkg/auth" +) + +type Provider struct{} + +var singleton *Provider = &Provider{} + +type NixCacheConfig struct { + URI string + Credentials types.Credentials +} + +func (n NixCacheConfig) CredentialsEnvVars() []string { + env := []string{} + if n.Credentials.AccessKeyId != nil { + env = append(env, "AWS_ACCESS_KEY_ID="+*n.Credentials.AccessKeyId) + } + if n.Credentials.SecretKey != nil { + env = append(env, "AWS_SECRET_ACCESS_KEY="+*n.Credentials.SecretKey) + } + if n.Credentials.SessionToken != nil { + env = append(env, "AWS_SESSION_TOKEN="+*n.Credentials.SessionToken) + } + return env +} + +func Get() *Provider { + return singleton +} + +// Config returns the URI or the nix bin cache and AWS credentials if available. +// Nix calls the URI a substituter. +// A substituter is a bin cache URI that nix can use to fetch pre-built +// binaries from. +func (p *Provider) Config(ctx context.Context) (NixCacheConfig, error) { + token, err := identity.Get().GenSession(ctx) + + if errors.Is(err, auth.ErrNotLoggedIn) { + // DEVBOX_NIX_BINCACHE_URI seems like a friendlier name than "substituter" + return NixCacheConfig{ + URI: os.Getenv("DEVBOX_NIX_BINCACHE_URI"), + }, nil + } else if err != nil { + return NixCacheConfig{}, err + } + + apiClient := api.NewClient(ctx, build.JetpackAPIHost(), token) + binCacheResponse, err := apiClient.GetBinCache(ctx) + if err != nil { + return NixCacheConfig{}, err + } + + checkIfUserCanAddSubstituter(ctx) + + return NixCacheConfig{ + URI: binCacheResponse.NixBinCacheUri, + Credentials: types.Credentials{ + AccessKeyId: aws.String(binCacheResponse.GetNixBinCacheCredentials().GetAccessKeyId()), + SecretKey: aws.String(binCacheResponse.GetNixBinCacheCredentials().GetSecretKey()), + SessionToken: aws.String(binCacheResponse.GetNixBinCacheCredentials().GetSessionToken()), + }, + }, nil +} + +func checkIfUserCanAddSubstituter(ctx context.Context) { + // we need to ensure that the user can actually use the extra + // substituter. If the user did a root install, then we need to add + // the trusted user/substituter to the nix.conf file and restart the daemon. + + // This check is not perfect, so we still try to use the substituter even if + // it fails + + // TODOs: + // * Also check if cache is enabled in nix.conf + // * Test on single user install + // * Automate making user trusted if needed + if !nix.IsUserTrusted(ctx) { + ux.Fwarning( + os.Stderr, + "In order to use a custom nix cache you must be a trusted user. Please "+ + "add your username to nix.conf (usually located at /etc/nix/nix.conf)"+ + " and restart the nix daemon.", + ) + } +} diff --git a/internal/devbox/providers/providers.go b/internal/devbox/providers/providers.go new file mode 100644 index 00000000000..058758d9f6e --- /dev/null +++ b/internal/devbox/providers/providers.go @@ -0,0 +1,21 @@ +package providers + +import ( + "go.jetpack.io/devbox/internal/devbox/providers/identity" + "go.jetpack.io/devbox/internal/devbox/providers/nixcache" +) + +// Providers is a struct that contains all the providers that devbox uses. +// A provider encapsulates data and/or logic that can affect devbox behavior. +// What a provider does can be influenced by the environment or external services. +// The goal is to centralize this logic and avoid conditionals in core devbox code. +// In the future we should allow dynamic providers as well which can help +// customize devbox behavior. +// +// Providers should have +// 1) A default behavior +// 2) A way to override that behavior (e.g. through environment variables, logged in state, etc.) +type Providers struct { + NixCache nixcache.Provider + Identity identity.Provider +} diff --git a/internal/devbox/secrets.go b/internal/devbox/secrets.go index 4b0e071226c..f8c43ae79ce 100644 --- a/internal/devbox/secrets.go +++ b/internal/devbox/secrets.go @@ -5,7 +5,6 @@ import ( "go.jetpack.io/devbox/internal/build" "go.jetpack.io/envsec/pkg/envsec" - "go.jetpack.io/envsec/pkg/stores/jetstore" "go.jetpack.io/pkg/envvar" ) @@ -18,7 +17,6 @@ func (d *Devbox) UninitializedSecrets(ctx context.Context) *envsec.Envsec { }, IsDev: build.IsDev, Stderr: d.stderr, - Store: &jetstore.JetpackAPIStore{}, WorkingDir: d.ProjectDir(), } } diff --git a/internal/nix/build.go b/internal/nix/build.go index d0684ec6319..cb7090bdb32 100644 --- a/internal/nix/build.go +++ b/internal/nix/build.go @@ -13,6 +13,7 @@ import ( type BuildArgs struct { AllowInsecure bool + Env []string ExtraSubstituter string Flags []string Writer io.Writer @@ -28,7 +29,7 @@ func Build(ctx context.Context, args *BuildArgs, installables ...string) error { if args.ExtraSubstituter != "" { cmd.Args = append(cmd.Args, "--extra-substituters", args.ExtraSubstituter) } - cmd.Env = allowUnfreeEnv(os.Environ()) + cmd.Env = append(allowUnfreeEnv(os.Environ()), args.Env...) if args.AllowInsecure { debug.Log("Setting Allow-insecure env-var\n") cmd.Env = allowInsecureEnv(cmd.Env) diff --git a/internal/nix/nix.go b/internal/nix/nix.go index 470750195b1..070bde6e96a 100644 --- a/internal/nix/nix.go +++ b/internal/nix/nix.go @@ -10,9 +10,11 @@ import ( "io/fs" "os" "os/exec" + "os/user" "path/filepath" "regexp" "runtime/trace" + "slices" "strings" "github.com/pkg/errors" @@ -298,3 +300,27 @@ func parseInsecurePackagesFromExitError(errorMsg string) []string { return insecurePackages } + +func IsUserTrusted(ctx context.Context) bool { + cmd := commandContext(ctx, "show-config", "--json") + out, err := cmd.Output() + if err != nil { + return false + } + + var config struct { + TrustedUsers struct { + Value []string `json:"value"` + } `json:"trusted-users"` + } + if err := json.Unmarshal(out, &config); err != nil { + return false + } + + u, err := user.Current() + if err != nil { + return false + } + + return slices.Contains(config.TrustedUsers.Value, u.Username) +}