Skip to content

Commit 13cef7d

Browse files
kylecarbsf0ssel
andauthored
feat: Support caching provisioner assets (coder#574)
* feat: Add AWS instance identity authentication This allows zero-trust authentication for all AWS instances. Prior to this, AWS instances could be used by passing `CODER_TOKEN` as an environment variable to the startup script. AWS explicitly states that secrets should not be passed in startup scripts because it's user-readable. * feat: Support caching provisioner assets This caches the Terraform binary, and Terraform plugins. Eventually, it could cache other temporary files. * chore: fix linter Co-authored-by: Garrett <garrett@coder.com>
1 parent 9485fd6 commit 13cef7d

File tree

4 files changed

+23
-5
lines changed

4 files changed

+23
-5
lines changed

cli/start.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"net/url"
1414
"os"
1515
"os/signal"
16+
"path/filepath"
1617
"time"
1718

1819
"github.com/briandowns/spinner"
@@ -42,6 +43,7 @@ func start() *cobra.Command {
4243
var (
4344
accessURL string
4445
address string
46+
cacheDir string
4547
dev bool
4648
postgresURL string
4749
// provisionerDaemonCount is a uint8 to ensure a number > 0.
@@ -161,7 +163,7 @@ func start() *cobra.Command {
161163

162164
provisionerDaemons := make([]*provisionerd.Server, 0)
163165
for i := 0; uint8(i) < provisionerDaemonCount; i++ {
164-
daemonClose, err := newProvisionerDaemon(cmd.Context(), client, logger)
166+
daemonClose, err := newProvisionerDaemon(cmd.Context(), client, logger, cacheDir)
165167
if err != nil {
166168
return xerrors.Errorf("create provisioner daemon: %w", err)
167169
}
@@ -305,6 +307,8 @@ func start() *cobra.Command {
305307

306308
cliflag.StringVarP(root.Flags(), &accessURL, "access-url", "", "CODER_ACCESS_URL", "", "Specifies the external URL to access Coder")
307309
cliflag.StringVarP(root.Flags(), &address, "address", "a", "CODER_ADDRESS", "127.0.0.1:3000", "The address to serve the API and dashboard")
310+
// systemd uses the CACHE_DIRECTORY environment variable!
311+
cliflag.StringVarP(root.Flags(), &cacheDir, "cache-dir", "", "CACHE_DIRECTORY", filepath.Join(os.TempDir(), ".coder-cache"), "Specifies a directory to cache binaries for provision operations.")
308312
cliflag.BoolVarP(root.Flags(), &dev, "dev", "", "CODER_DEV_MODE", false, "Serve Coder in dev mode for tinkering")
309313
cliflag.StringVarP(root.Flags(), &postgresURL, "postgres-url", "", "CODER_PG_CONNECTION_URL", "", "URL of a PostgreSQL database to connect to")
310314
cliflag.Uint8VarP(root.Flags(), &provisionerDaemonCount, "provisioner-daemons", "", "CODER_PROVISIONER_DAEMONS", 1, "The amount of provisioner daemons to create on start.")
@@ -358,14 +362,15 @@ func createFirstUser(cmd *cobra.Command, client *codersdk.Client, cfg config.Roo
358362
return nil
359363
}
360364

361-
func newProvisionerDaemon(ctx context.Context, client *codersdk.Client, logger slog.Logger) (*provisionerd.Server, error) {
365+
func newProvisionerDaemon(ctx context.Context, client *codersdk.Client, logger slog.Logger, cacheDir string) (*provisionerd.Server, error) {
362366
terraformClient, terraformServer := provisionersdk.TransportPipe()
363367
go func() {
364368
err := terraform.Serve(ctx, &terraform.ServeOptions{
365369
ServeOptions: &provisionersdk.ServeOptions{
366370
Listener: terraformServer,
367371
},
368-
Logger: logger,
372+
CachePath: cacheDir,
373+
Logger: logger,
369374
})
370375
if err != nil {
371376
panic(err)

coder.service

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ PrivateTmp=yes
1616
PrivateDevices=yes
1717
SecureBits=keep-caps
1818
AmbientCapabilities=CAP_IPC_LOCK
19+
CacheDirectory=coder
1920
CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK CAP_NET_BIND_SERVICE
2021
NoNewPrivileges=yes
2122
ExecStart=/usr/bin/coder start

provisioner/terraform/provision.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ func (t *terraform) Provision(stream proto.DRPCProvisioner_ProvisionStream) erro
8787
})
8888
}
8989
}()
90+
if t.cachePath != "" {
91+
err = terraform.SetEnv(map[string]string{
92+
"TF_PLUGIN_CACHE_DIR": t.cachePath,
93+
})
94+
if err != nil {
95+
return xerrors.Errorf("set terraform plugin cache dir: %w", err)
96+
}
97+
}
9098
terraform.SetStdout(writer)
9199
t.logger.Debug(shutdown, "running initialization")
92100
err = terraform.Init(shutdown)

provisioner/terraform/serve.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type ServeOptions struct {
3434
// BinaryPath specifies the "terraform" binary to use.
3535
// If omitted, the $PATH will attempt to find it.
3636
BinaryPath string
37+
CachePath string
3738
Logger slog.Logger
3839
}
3940

@@ -43,8 +44,9 @@ func Serve(ctx context.Context, options *ServeOptions) error {
4344
binaryPath, err := exec.LookPath("terraform")
4445
if err != nil {
4546
installer := &releases.ExactVersion{
46-
Product: product.Terraform,
47-
Version: version.Must(version.NewVersion("1.1.7")),
47+
InstallDir: options.CachePath,
48+
Product: product.Terraform,
49+
Version: version.Must(version.NewVersion("1.1.7")),
4850
}
4951

5052
execPath, err := installer.Install(ctx)
@@ -58,11 +60,13 @@ func Serve(ctx context.Context, options *ServeOptions) error {
5860
}
5961
return provisionersdk.Serve(ctx, &terraform{
6062
binaryPath: options.BinaryPath,
63+
cachePath: options.CachePath,
6164
logger: options.Logger,
6265
}, options.ServeOptions)
6366
}
6467

6568
type terraform struct {
6669
binaryPath string
70+
cachePath string
6771
logger slog.Logger
6872
}

0 commit comments

Comments
 (0)