Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate peer: check bigquery permissions #1119

Merged
merged 6 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions flow/cmd/validate_peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ func (h *FlowRequestHandler) ValidatePeer(
if err != nil {
return &protos.ValidatePeerResponse{
Status: protos.ValidatePeerStatus_INVALID,
Message: fmt.Sprintf("peer type is missing or "+
"your requested configuration for %s peer %s was invalidated: %s",
Message: fmt.Sprintf("%s peer %s was invalidated: %s",
req.Peer.Type, req.Peer.Name, err),
}, nil
}
Expand Down
60 changes: 56 additions & 4 deletions flow/connectors/bigquery/bigquery.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package connbigquery
import (
"context"
"encoding/json"
"errors"
"fmt"
"log/slog"
"reflect"
Expand Down Expand Up @@ -142,6 +143,51 @@ func (bqsa *BigQueryServiceAccount) CreateStorageClient(ctx context.Context) (*s
return client, nil
}

// TableCheck:
// 1. Creates a table
// 2. Inserts one row into the table
// 3. Deletes the table
func TableCheck(ctx context.Context, client *bigquery.Client, dataset string, project string) error {
dummyTable := "peerdb_validate_dummy_" + shared.RandomString(4)

newTable := client.DatasetInProject(project, dataset).Table(dummyTable)

createErr := newTable.Create(ctx, &bigquery.TableMetadata{
Schema: []*bigquery.FieldSchema{
{
Name: "dummy",
Type: bigquery.BooleanFieldType,
Repeated: false,
},
},
})
if createErr != nil {
return fmt.Errorf("unable to validate table creation within dataset: %w. "+
"Please check if bigquery.tables.create permission has been granted", createErr)
}

var errs []error
insertQuery := client.Query(fmt.Sprintf("INSERT INTO %s VALUES(true)", dummyTable))
insertQuery.DefaultDatasetID = dataset
insertQuery.DefaultProjectID = project
_, insertErr := insertQuery.Run(ctx)
if insertErr != nil {
errs = append(errs, fmt.Errorf("unable to validate insertion into table: %w. ", insertErr))
}

// Drop the table
deleteErr := newTable.Delete(ctx)
if deleteErr != nil {
errs = append(errs, fmt.Errorf("unable to delete table :%w. ", deleteErr))
Amogh-Bharadwaj marked this conversation as resolved.
Show resolved Hide resolved
}

if len(errs) > 0 {
return errors.Join(errs...)
}

return nil
}

// NewBigQueryConnector creates a new BigQueryConnector from a PeerConnectionConfig.
func NewBigQueryConnector(ctx context.Context, config *protos.BigqueryConfig) (*BigQueryConnector, error) {
bqsa, err := NewBigQueryServiceAccount(config)
Expand All @@ -166,10 +212,16 @@ func NewBigQueryConnector(ctx context.Context, config *protos.BigqueryConfig) (*
return nil, fmt.Errorf("failed to create BigQuery client: %v", err)
}

_, checkErr := client.DatasetInProject(projectID, datasetID).Metadata(ctx)
if checkErr != nil {
slog.ErrorContext(ctx, "failed to get dataset metadata", slog.Any("error", checkErr))
return nil, fmt.Errorf("failed to get dataset metadata: %v", checkErr)
_, datasetErr := client.DatasetInProject(projectID, datasetID).Metadata(ctx)
if datasetErr != nil {
slog.ErrorContext(ctx, "failed to get dataset metadata", slog.Any("error", datasetErr))
return nil, fmt.Errorf("failed to get dataset metadata: %v", datasetErr)
}

permissionErr := TableCheck(ctx, client, datasetID, projectID)
if permissionErr != nil {
slog.ErrorContext(ctx, "failed to get run mock table check", slog.Any("error", permissionErr))
return nil, permissionErr
}

storageClient, err := bqsa.CreateStorageClient(ctx)
Expand Down
6 changes: 3 additions & 3 deletions ui/components/PeerForms/BigqueryConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ export default function BigqueryForm(props: BQProps) {
A service account JSON file in BigQuery is a file that contains
information which allows PeerDB to securely access BigQuery resources.
</Label>
<Label
as={Link}
<Link
style={{ color: 'teal', textDecoration: 'underline' }}
href='https://cloud.google.com/bigquery/docs/authentication/service-account-file'
target='_blank'
>
Creating a service account file
</Label>
</Link>
<RowWithTextField
label={
<Label>
Expand Down
Loading