diff --git a/bindings/gcp/bucket/bucket.go b/bindings/gcp/bucket/bucket.go index 991ae3121..dd1bfddca 100644 --- a/bindings/gcp/bucket/bucket.go +++ b/bindings/gcp/bucket/bucket.go @@ -104,13 +104,7 @@ func (g *GCPStorage) Init(ctx context.Context, metadata bindings.Metadata) error return err } - b, err := json.Marshal(m) - if err != nil { - return err - } - - clientOptions := option.WithCredentialsJSON(b) - client, err := storage.NewClient(ctx, clientOptions) + client, err := g.getClient(ctx, m) if err != nil { return err } @@ -121,6 +115,41 @@ func (g *GCPStorage) Init(ctx context.Context, metadata bindings.Metadata) error return nil } +func (g *GCPStorage) getClient(ctx context.Context, m *gcpMetadata) (*storage.Client, error) { + var client *storage.Client + var err error + + if m.Bucket == "" { + return nil, errors.New("missing property `bucket` in metadata") + } + if m.ProjectID == "" { + return nil, errors.New("missing property `project_id` in metadata") + } + + // Explicit authentication + if m.PrivateKeyID != "" { + var b []byte + b, err = json.Marshal(m) + if err != nil { + return nil, err + } + + clientOptions := option.WithCredentialsJSON(b) + client, err = storage.NewClient(ctx, clientOptions) + if err != nil { + return nil, err + } + } else { + // Implicit authentication, using GCP Application Default Credentials (ADC) + // Credentials search order: https://cloud.google.com/docs/authentication/application-default-credentials#order + client, err = storage.NewClient(ctx) + if err != nil { + return nil, err + } + } + return client, nil +} + func (g *GCPStorage) parseMetadata(meta bindings.Metadata) (*gcpMetadata, error) { m := gcpMetadata{} err := kitmd.DecodeMetadata(meta.Properties, &m) diff --git a/bindings/gcp/bucket/bucket_test.go b/bindings/gcp/bucket/bucket_test.go index b689751c0..663e48e5c 100644 --- a/bindings/gcp/bucket/bucket_test.go +++ b/bindings/gcp/bucket/bucket_test.go @@ -15,6 +15,7 @@ package bucket import ( "encoding/json" + "errors" "testing" "github.com/stretchr/testify/assert" @@ -234,6 +235,30 @@ func TestMergeWithRequestMetadata(t *testing.T) { }) } +func TestInit(t *testing.T) { + t.Run("Init missing bucket from metadata", func(t *testing.T) { + m := bindings.Metadata{} + m.Properties = map[string]string{ + "projectID": "my_project_id", + } + gs := GCPStorage{logger: logger.NewLogger("test")} + err := gs.Init(t.Context(), m) + require.Error(t, err) + assert.Equal(t, err, errors.New("missing property `bucket` in metadata")) + }) + + t.Run("Init missing projectID from metadata", func(t *testing.T) { + m := bindings.Metadata{} + m.Properties = map[string]string{ + "bucket": "my_bucket", + } + gs := GCPStorage{logger: logger.NewLogger("test")} + err := gs.Init(t.Context(), m) + require.Error(t, err) + assert.Equal(t, err, errors.New("missing property `project_id` in metadata")) + }) +} + func TestGetOption(t *testing.T) { gs := GCPStorage{logger: logger.NewLogger("test")} gs.metadata = &gcpMetadata{} diff --git a/go.mod b/go.mod index 0d767a2d0..3d3f9b3e4 100644 --- a/go.mod +++ b/go.mod @@ -107,7 +107,7 @@ require ( github.com/redis/go-redis/v9 v9.6.3 github.com/riferrei/srclient v0.6.0 github.com/sendgrid/sendgrid-go v3.13.0+incompatible - github.com/sijms/go-ora/v2 v2.7.18 + github.com/sijms/go-ora/v2 v2.8.22 github.com/spf13/cast v1.6.0 github.com/spiffe/go-spiffe/v2 v2.1.7 github.com/stealthrocket/wasi-go v0.8.1-0.20230912180546-8efbab50fb58 @@ -227,7 +227,7 @@ require ( github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect github.com/eapache/queue v1.1.0 // indirect github.com/emicklei/go-restful/v3 v3.10.1 // indirect - github.com/emirpasic/gods v1.12.0 // indirect + github.com/emirpasic/gods v1.18.1 // indirect github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect diff --git a/go.sum b/go.sum index e7260eef5..8a8e64075 100644 --- a/go.sum +++ b/go.sum @@ -567,8 +567,9 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -1524,8 +1525,8 @@ github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sijms/go-ora/v2 v2.7.18 h1:xl9CUeBlFi261AOKekiiFnfcp3ojHFEedLxIzsj909E= -github.com/sijms/go-ora/v2 v2.7.18/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl4FWlH6xk= +github.com/sijms/go-ora/v2 v2.8.22 h1:3ABgRzVKxS439cEgSLjFKutIwOyhnyi4oOSBywEdOlU= +github.com/sijms/go-ora/v2 v2.8.22/go.mod h1:QgFInVi3ZWyqAiJwzBQA+nbKYKH77tdp1PYoCqhR2dU= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= diff --git a/secretstores/gcp/secretmanager/secretmanager.go b/secretstores/gcp/secretmanager/secretmanager.go index 19c795204..21d20566f 100644 --- a/secretstores/gcp/secretmanager/secretmanager.go +++ b/secretstores/gcp/secretmanager/secretmanager.go @@ -88,12 +88,38 @@ func (s *Store) Init(ctx context.Context, metadataRaw secretstores.Metadata) err } func (s *Store) getClient(ctx context.Context, metadata *GcpSecretManagerMetadata) (*secretmanager.Client, error) { - b, _ := json.Marshal(metadata) - clientOptions := option.WithCredentialsJSON(b) + var client *secretmanager.Client + var err error - client, err := secretmanager.NewClient(ctx, clientOptions) - if err != nil { - return nil, err + if metadata.ProjectID == "" { + return nil, errors.New("missing property `project_id` in metadata") + } + + // Explicit authentication + if metadata.PrivateKeyID != "" { + if metadata.Type == "" { + return nil, errors.New("missing property `type` in metadata") + } + if metadata.PrivateKey == "" { + return nil, errors.New("missing property `private_key` in metadata") + } + if metadata.ClientEmail == "" { + return nil, errors.New("missing property `client_email` in metadata") + } + + b, _ := json.Marshal(metadata) + clientOptions := option.WithCredentialsJSON(b) + client, err = secretmanager.NewClient(ctx, clientOptions) + if err != nil { + return nil, err + } + } else { + // Implicit authentication, using GCP Application Default Credentials (ADC) + // Credentials search order: https://cloud.google.com/docs/authentication/application-default-credentials#order + client, err = secretmanager.NewClient(ctx) + if err != nil { + return nil, err + } } return client, nil @@ -183,18 +209,9 @@ func (s *Store) parseSecretManagerMetadata(metadataRaw secretstores.Metadata) (* return nil, fmt.Errorf("failed to decode metadata: %w", err) } - if meta.Type == "" { - return nil, errors.New("missing property `type` in metadata") - } if meta.ProjectID == "" { return nil, errors.New("missing property `project_id` in metadata") } - if meta.PrivateKey == "" { - return nil, errors.New("missing property `private_key` in metadata") - } - if meta.ClientEmail == "" { - return nil, errors.New("missing property `client_email` in metadata") - } return &meta, nil } diff --git a/secretstores/gcp/secretmanager/secretmanager_test.go b/secretstores/gcp/secretmanager/secretmanager_test.go index 483b31425..413d7e0bb 100644 --- a/secretstores/gcp/secretmanager/secretmanager_test.go +++ b/secretstores/gcp/secretmanager/secretmanager_test.go @@ -76,11 +76,38 @@ func TestInit(t *testing.T) { t.Run("Init with missing `type` metadata", func(t *testing.T) { m.Properties = map[string]string{ - "dummy": "a", + "dummy": "a", + "private_key_id": "a", + "project_id": "a", } err := sm.Init(ctx, m) require.Error(t, err) - assert.Equal(t, err, errors.New("missing property `type` in metadata")) + assert.Equal(t, errors.New("failed to setup secretmanager client: missing property `type` in metadata"), err) + }) + + t.Run("Init with missing `private_key` metadata", func(t *testing.T) { + m.Properties = map[string]string{ + "dummy": "a", + "private_key_id": "a", + "type": "a", + "project_id": "a", + } + err := sm.Init(ctx, m) + require.Error(t, err) + assert.Equal(t, errors.New("failed to setup secretmanager client: missing property `private_key` in metadata"), err) + }) + + t.Run("Init with missing `client_email` metadata", func(t *testing.T) { + m.Properties = map[string]string{ + "dummy": "a", + "private_key_id": "a", + "private_key": "a", + "type": "a", + "project_id": "a", + } + err := sm.Init(ctx, m) + require.Error(t, err) + assert.Equal(t, errors.New("failed to setup secretmanager client: missing property `client_email` in metadata"), err) }) t.Run("Init with missing `project_id` metadata", func(t *testing.T) { @@ -91,6 +118,22 @@ func TestInit(t *testing.T) { require.Error(t, err) assert.Equal(t, err, errors.New("missing property `project_id` in metadata")) }) + + t.Run("Init with missing `project_id` metadata", func(t *testing.T) { + m.Properties = map[string]string{ + "type": "service_account", + } + err := sm.Init(ctx, m) + require.Error(t, err) + assert.Equal(t, err, errors.New("missing property `project_id` in metadata")) + }) + + t.Run("Init with empty metadata", func(t *testing.T) { + m.Properties = map[string]string{} + err := sm.Init(ctx, m) + require.Error(t, err) + assert.Equal(t, err, errors.New("missing property `project_id` in metadata")) + }) } func TestGetSecret(t *testing.T) { diff --git a/state/oracledatabase/oracledatabaseaccess.go b/state/oracledatabase/oracledatabaseaccess.go index 9a62ce6d4..fdd5374a5 100644 --- a/state/oracledatabase/oracledatabaseaccess.go +++ b/state/oracledatabase/oracledatabaseaccess.go @@ -514,8 +514,16 @@ func (o *oracleDatabaseAccess) ensureStateTable(stateTableName string) error { } func tableExists(db *sql.DB, tableName string) (bool, error) { - var tblCount int32 - err := db.QueryRow("SELECT count(table_name) tbl_count FROM user_tables WHERE table_name = upper(:tablename)", tableName).Scan(&tblCount) - exists := tblCount > 0 - return exists, err + //nolint:gosec + query := fmt.Sprintf("SELECT 1 FROM %s WHERE ROWNUM = 1", tableName) + + var dummy int + err := db.QueryRow(query).Scan(&dummy) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return true, nil // Table exists but is empty + } + return false, nil // Likely a table does not exist error + } + return true, nil }