From 33b575f4521a91bd69d5019eef78e5db1800596d Mon Sep 17 00:00:00 2001 From: "Jorge E. Moreira" Date: Thu, 16 Nov 2023 16:57:56 -0800 Subject: [PATCH] Allow creating devices without build api credentials --- build/package/host/etc/cvdr.toml | 6 ++++ pkg/app/secrets/empty.go | 3 +- pkg/cli/cli.go | 3 ++ pkg/cli/cli_test.go | 1 + pkg/cli/config.go | 4 ++- pkg/cli/config_test.go | 1 + pkg/cli/cvd.go | 56 ++++++++++++++++++++++++-------- 7 files changed, 57 insertions(+), 17 deletions(-) diff --git a/build/package/host/etc/cvdr.toml b/build/package/host/etc/cvdr.toml index cbfd5ba5..879cbf96 100644 --- a/build/package/host/etc/cvdr.toml +++ b/build/package/host/etc/cvdr.toml @@ -25,6 +25,12 @@ # files forever. # KeepLogFilesDays = 30 +# Source for the Build API credentials to be used on cvd create operations. +# Possible values are: +# - "injected": Use credentials stored in the server. +# - "none": Don't use Build API credentials. +# CredentialsSource = "injected" + # The host.GCP section provides default configuration values for hosts created # using the GCP Cloud Provider. Other providers will have their own # host. sections when added. diff --git a/pkg/app/secrets/empty.go b/pkg/app/secrets/empty.go index 7b8d5fc5..d391acaa 100644 --- a/pkg/app/secrets/empty.go +++ b/pkg/app/secrets/empty.go @@ -17,7 +17,7 @@ package secrets const EmptySMType = "" // A secret manager that always returns empty string. -type EmptySecretManager struct {} +type EmptySecretManager struct{} func NewEmptySecretManager() *EmptySecretManager { return &EmptySecretManager{} @@ -30,4 +30,3 @@ func (sm *EmptySecretManager) OAuth2ClientID() string { func (sm *EmptySecretManager) OAuth2ClientSecret() string { return "" } - diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index de2e9512..04e1e068 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -97,6 +97,7 @@ const ( systemImgBuildTargetFlag = "system_build_target" numInstancesFlag = "num_instances" autoConnectFlag = "auto_connect" + credentialsSourceFlag = "credentials_source" ) const ( @@ -488,6 +489,8 @@ func cvdCommands(opts *subCommandOpts) []*cobra.Command { "Creates multiple instances with the same artifacts. Only relevant if given a single build source") create.Flags().BoolVar(&createFlags.AutoConnect, autoConnectFlag, true, "Automatically connect through ADB after device is created.") + create.Flags().StringVar(&createFlags.CredentialsSource, credentialsSourceFlag, opts.InitialConfig.CredentialsSource, + "Source for the Build API OAuth2 credentials") // Host flags createHostFlags := []struct { ValueRef *string diff --git a/pkg/cli/cli_test.go b/pkg/cli/cli_test.go index 3594b526..ec3aa452 100644 --- a/pkg/cli/cli_test.go +++ b/pkg/cli/cli_test.go @@ -205,6 +205,7 @@ func TestCommandSucceeds(t *testing.T) { Args: append(test.Args, "--service_url="+serviceURL), InitialConfig: Config{ ConnectionControlDir: t.TempDir(), + CredentialsSource: "none", }, ServiceBuilder: func(opts *client.ServiceOptions) (client.Service, error) { return &fakeService{}, nil diff --git a/pkg/cli/config.go b/pkg/cli/config.go index e123316c..695f197f 100644 --- a/pkg/cli/config.go +++ b/pkg/cli/config.go @@ -41,6 +41,7 @@ type Config struct { HTTPProxy string ConnectionControlDir string KeepLogFilesDays int + CredentialsSource string Host HostConfig } @@ -55,7 +56,8 @@ func (c *Config) LogFilesDeleteThreshold() time.Duration { func BaseConfig() *Config { return &Config{ ConnectionControlDir: "~/.cvdr/connections", - KeepLogFilesDays: 30, // A default is needed to not keep forever + KeepLogFilesDays: 30, // A default is needed to not keep forever + CredentialsSource: NoneCredentialsSource, // Default needed because empty string is invalid } } diff --git a/pkg/cli/config_test.go b/pkg/cli/config_test.go index 1b0f558a..1260f5a4 100644 --- a/pkg/cli/config_test.go +++ b/pkg/cli/config_test.go @@ -104,6 +104,7 @@ MachineType = "machine-type-bar" Zone: "zone-bar", KeepLogFilesDays: 0, ConnectionControlDir: "~/.cvdr/connections", + CredentialsSource: NoneCredentialsSource, Host: HostConfig{ GCP: GCPHostConfig{ MachineType: "machine-type-bar", diff --git a/pkg/cli/cvd.go b/pkg/cli/cvd.go index 32389039..0783af17 100644 --- a/pkg/cli/cvd.go +++ b/pkg/cli/cvd.go @@ -62,6 +62,11 @@ func NewRemoteCVD(url, host string, cvd *hoapi.CVD) *RemoteCVD { } } +const ( + NoneCredentialsSource = "none" + InjectedCredentialsSource = "injected" +) + type CreateCVDOpts struct { Host string MainBuild hoapi.AndroidCIBuild @@ -75,7 +80,8 @@ type CreateCVDOpts struct { // Example: https://cs.android.com/android/platform/superproject/main/+/main:device/google/cuttlefish/host/cvd_test_configs/main_phone-main_watch.json;drc=b2e8f4f014abb7f9cb56c0ae199334aacb04542d EnvConfig map[string]interface{} // If true, perform the ADB connection automatically. - AutoConnect bool + AutoConnect bool + CredentialsSource string } func (o *CreateCVDOpts) AdditionalInstancesNum() uint32 { @@ -86,7 +92,10 @@ func (o *CreateCVDOpts) AdditionalInstancesNum() uint32 { } func createCVD(service client.Service, createOpts CreateCVDOpts, statePrinter *statePrinter) ([]*RemoteCVD, error) { - creator := newCVDCreator(service, createOpts, statePrinter) + creator, err := newCVDCreator(service, createOpts, statePrinter) + if err != nil { + return nil, fmt.Errorf("failed to create cvd: %w", err) + } cvds, err := creator.Create() if err != nil { return nil, fmt.Errorf("failed to create cvd: %w", err) @@ -98,18 +107,26 @@ func createCVD(service client.Service, createOpts CreateCVDOpts, statePrinter *s return result, nil } +type CredentialsFactory func() string + type cvdCreator struct { - service client.Service - opts CreateCVDOpts - statePrinter *statePrinter + service client.Service + opts CreateCVDOpts + statePrinter *statePrinter + credentialsFactory CredentialsFactory } -func newCVDCreator(service client.Service, opts CreateCVDOpts, statePrinter *statePrinter) *cvdCreator { - return &cvdCreator{ - service: service, - opts: opts, - statePrinter: statePrinter, +func newCVDCreator(service client.Service, opts CreateCVDOpts, statePrinter *statePrinter) (*cvdCreator, error) { + cf, err := credentialsFactoryFromSource(opts.CredentialsSource) + if err != nil { + return nil, err } + return &cvdCreator{ + service: service, + opts: opts, + statePrinter: statePrinter, + credentialsFactory: cf, + }, nil } func (c *cvdCreator) Create() ([]*hoapi.CVD, error) { @@ -150,7 +167,7 @@ func (c *cvdCreator) createCVDFromLocalBuild() ([]*hoapi.CVD, error) { }, AdditionalInstancesNum: c.opts.AdditionalInstancesNum(), } - res, err := c.service.HostService(c.opts.Host).CreateCVD(&req, client.InjectedCredentials) + res, err := c.service.HostService(c.opts.Host).CreateCVD(&req, c.credentialsFactory()) if err != nil { return nil, err } @@ -175,7 +192,7 @@ func (c *cvdCreator) createWithCanonicalConfig() ([]*hoapi.CVD, error) { EnvConfig: c.opts.EnvConfig, } c.statePrinter.Print(stateMsgFetchAndStart) - res, err := c.service.HostService(c.opts.Host).CreateCVD(createReq, client.InjectedCredentials) + res, err := c.service.HostService(c.opts.Host).CreateCVD(createReq, c.credentialsFactory()) c.statePrinter.PrintDone(stateMsgFetchAndStart, err) if err != nil { return nil, err @@ -199,7 +216,7 @@ func (c *cvdCreator) createWithOpts() ([]*hoapi.CVD, error) { AndroidCIBundle: &hoapi.AndroidCIBundle{Build: mainBuild, Type: hoapi.MainBundleType}, } c.statePrinter.Print(stateMsgFetchMainBundle) - fetchMainBuildRes, err := c.service.HostService(c.opts.Host).FetchArtifacts(fetchReq, client.InjectedCredentials) + fetchMainBuildRes, err := c.service.HostService(c.opts.Host).FetchArtifacts(fetchReq, c.credentialsFactory()) c.statePrinter.PrintDone(stateMsgFetchMainBundle, err) if err != nil { return nil, err @@ -218,7 +235,7 @@ func (c *cvdCreator) createWithOpts() ([]*hoapi.CVD, error) { AdditionalInstancesNum: c.opts.AdditionalInstancesNum(), } c.statePrinter.Print(stateMsgStartCVD) - res, err := c.service.HostService(c.opts.Host).CreateCVD(createReq, client.InjectedCredentials) + res, err := c.service.HostService(c.opts.Host).CreateCVD(createReq, c.credentialsFactory()) c.statePrinter.PrintDone(stateMsgStartCVD, err) if err != nil { return nil, err @@ -226,6 +243,17 @@ func (c *cvdCreator) createWithOpts() ([]*hoapi.CVD, error) { return res.CVDs, nil } +func credentialsFactoryFromSource(source string) (CredentialsFactory, error) { + switch source { + case NoneCredentialsSource: + return func() string { return "" }, nil + case InjectedCredentialsSource: + return func() string { return client.InjectedCredentials }, nil + default: + return nil, fmt.Errorf("unknown credentials source: %s", source) + } +} + type cvdListResult struct { Result []*RemoteCVD Error error