Skip to content

Commit

Permalink
externalconn: support SHOW CREATE EXTERNAL CONNECTION
Browse files Browse the repository at this point in the history
This change adds support for `SHOW CREATE EXTERNAL CONNECTION`
and `SHOW CREATE ALL EXTERNAL CONNECTIONS` that displays the
connection name and the statement used to create the external
connection. This displays unredacted information of the underlying
resource and is therefore restricted to admin only or by the
owner of the external connection object.

Note, synthetic privileges do not have a concept of external
connections at the moment. So, the operations are limited to
admin only until that functionality is added.

Informs: #85905

Release note (sql change): Add support for `SHOW CREATE EXTERNAL CONNECTION`
and `SHOW CREATE ALL EXTERNAL CONNECTIONS` that displays the
connection name and the unredacted query used to create the external
connection. This can only be run by users of the admin role today.
  • Loading branch information
adityamaru committed Aug 17, 2022
1 parent 5f45e42 commit 41e20ce
Show file tree
Hide file tree
Showing 21 changed files with 472 additions and 22 deletions.
1 change: 1 addition & 0 deletions docs/generated/sql/bnf/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ FILES = [
"show_constraints_stmt",
"show_create_stmt",
"show_create_schedules_stmt",
"show_create_external_connections_stmt",
"show_databases_stmt",
"show_default_privileges_stmt",
"show_enums",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
show_create_external_connections_stmt ::=
'SHOW' 'CREATE' 'ALL' 'EXTERNAL' 'CONNECTIONS'
| 'SHOW' 'CREATE' 'EXTERNAL' 'CONNECTION' string_or_placeholder
1 change: 1 addition & 0 deletions docs/generated/sql/bnf/show_var.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ show_stmt ::=
| show_constraints_stmt
| show_create_stmt
| show_create_schedules_stmt
| show_create_external_connections_stmt
| show_local_or_tenant_csettings_stmt
| show_databases_stmt
| show_enums_stmt
Expand Down
6 changes: 6 additions & 0 deletions docs/generated/sql/bnf/stmt_block.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ show_stmt ::=
| show_constraints_stmt
| show_create_stmt
| show_create_schedules_stmt
| show_create_external_connections_stmt
| show_local_or_tenant_csettings_stmt
| show_databases_stmt
| show_enums_stmt
Expand Down Expand Up @@ -777,6 +778,10 @@ show_create_schedules_stmt ::=
'SHOW' 'CREATE' 'ALL' 'SCHEDULES'
| 'SHOW' 'CREATE' 'SCHEDULE' a_expr

show_create_external_connections_stmt ::=
'SHOW' 'CREATE' 'ALL' 'EXTERNAL' 'CONNECTIONS'
| 'SHOW' 'CREATE' 'EXTERNAL' 'CONNECTION' string_or_placeholder

show_local_or_tenant_csettings_stmt ::=
show_csettings_stmt
| show_csettings_stmt 'FOR' 'TENANT' d_expr
Expand Down Expand Up @@ -1008,6 +1013,7 @@ unreserved_keyword ::=
| 'CONFIGURATIONS'
| 'CONFIGURE'
| 'CONNECTION'
| 'CONNECTIONS'
| 'CONSTRAINTS'
| 'CONTROLCHANGEFEED'
| 'CONTROLJOB'
Expand Down
6 changes: 6 additions & 0 deletions pkg/ccl/cloudccl/externalconn/datadriven_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ func TestDataDriven(t *testing.T) {
}

case "query-sql":
if d.HasArg("user") {
var user string
d.ScanArgs(t, "user", &user)
resetToRootUser := externalConnTestCluster.SetSQLDBForUser(tenantID, user)
defer resetToRootUser()
}
var rows *gosql.Rows
var err error
if rows, err = tenant.QueryWithErr(d.Input); err != nil {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
subtest basic-show-create-ec

initialize tenant=10
----

disable-check-external-storage
----

disable-check-kms
----

exec-sql
CREATE EXTERNAL CONNECTION nodelocal AS 'nodelocal://1/foo';
----

exec-sql
CREATE EXTERNAL CONNECTION kms AS 'gs:///cmk?AUTH=implicit&CREDENTIALS=wont-be-redacted';
----

exec-sql
CREATE EXTERNAL CONNECTION kafka AS 'kafka://broker.address.com:9092';
----

query-sql
SHOW CREATE ALL EXTERNAL CONNECTIONS
----
kafka CREATE EXTERNAL CONNECTION 'kafka' AS 'kafka://broker.address.com:9092'
kms CREATE EXTERNAL CONNECTION 'kms' AS 'gs:///cmk?AUTH=implicit&CREDENTIALS=wont-be-redacted'
nodelocal CREATE EXTERNAL CONNECTION 'nodelocal' AS 'nodelocal://1/foo'

query-sql
SHOW CREATE EXTERNAL CONNECTION nodelocal
----
nodelocal CREATE EXTERNAL CONNECTION 'nodelocal' AS 'nodelocal://1/foo'

query-sql
SHOW CREATE EXTERNAL CONNECTION kms
----
kms CREATE EXTERNAL CONNECTION 'kms' AS 'gs:///cmk?AUTH=implicit&CREDENTIALS=wont-be-redacted'

query-sql
SHOW CREATE EXTERNAL CONNECTION kafka
----
kafka CREATE EXTERNAL CONNECTION 'kafka' AS 'kafka://broker.address.com:9092'


enable-check-external-storage
----

enable-check-kms
----

subtest end

subtest owner-or-admin

# Create an external connection as root, only root should be able to SHOW this object.
exec-sql
CREATE EXTERNAL CONNECTION foo AS 'nodelocal://1/foo'
----

exec-sql
CREATE USER testuser
----

exec-sql
GRANT SYSTEM EXTERNALCONNECTION TO testuser
----

query-sql user=testuser
SHOW CREATE ALL EXTERNAL CONNECTIONS
----
pq: must be admin to run `SHOW CREATE ALL EXTERNAL CONNECTIONS

query-sql user=testuser
SHOW CREATE EXTERNAL CONNECTION foo
----
pq: must be admin or owner of the External Connection "foo"

# Create External Connection where testuser is the owner, they should be able to SHOW this object.
exec-sql user=testuser
CREATE EXTERNAL CONNECTION bar AS 'nodelocal://1/foo'
----

query-sql user=testuser
SHOW CREATE ALL EXTERNAL CONNECTIONS
----
pq: must be admin to run `SHOW CREATE ALL EXTERNAL CONNECTIONS

# TODO(aditymaru): Synthetic privileges do not have a concept of owners. Once they do, testuser will
# be able to run this query successfully since they are the owner of the External Connection object.
# query-sql user=testuser
# SHOW CREATE EXTERNAL CONNECTION bar
# ----

subtest end
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
subtest basic-show-create-ec

disable-check-external-storage
----

disable-check-kms
----

exec-sql
CREATE EXTERNAL CONNECTION nodelocal AS 'nodelocal://1/foo';
----

exec-sql
CREATE EXTERNAL CONNECTION kms AS 'gs:///cmk?AUTH=implicit&CREDENTIALS=wont-be-redacted';
----

exec-sql
CREATE EXTERNAL CONNECTION kafka AS 'kafka://broker.address.com:9092';
----

query-sql
SHOW CREATE ALL EXTERNAL CONNECTIONS
----
kafka CREATE EXTERNAL CONNECTION 'kafka' AS 'kafka://broker.address.com:9092'
kms CREATE EXTERNAL CONNECTION 'kms' AS 'gs:///cmk?AUTH=implicit&CREDENTIALS=wont-be-redacted'
nodelocal CREATE EXTERNAL CONNECTION 'nodelocal' AS 'nodelocal://1/foo'

query-sql
SHOW CREATE EXTERNAL CONNECTION nodelocal
----
nodelocal CREATE EXTERNAL CONNECTION 'nodelocal' AS 'nodelocal://1/foo'

query-sql
SHOW CREATE EXTERNAL CONNECTION kms
----
kms CREATE EXTERNAL CONNECTION 'kms' AS 'gs:///cmk?AUTH=implicit&CREDENTIALS=wont-be-redacted'

query-sql
SHOW CREATE EXTERNAL CONNECTION kafka
----
kafka CREATE EXTERNAL CONNECTION 'kafka' AS 'kafka://broker.address.com:9092'

enable-check-external-storage
----

enable-check-kms
----

subtest end

subtest owner-or-admin

# Create an external connection as root, only root should be able to SHOW this object.
exec-sql
CREATE EXTERNAL CONNECTION foo AS 'nodelocal://1/foo'
----

exec-sql
CREATE USER testuser
----

exec-sql
GRANT SYSTEM EXTERNALCONNECTION TO testuser
----

query-sql user=testuser
SHOW CREATE ALL EXTERNAL CONNECTIONS
----
pq: must be admin to run `SHOW CREATE ALL EXTERNAL CONNECTIONS

query-sql user=testuser
SHOW CREATE EXTERNAL CONNECTION foo
----
pq: must be admin or owner of the External Connection "foo"

# Create External Connection where testuser is the owner, they should be able to SHOW this object.
exec-sql user=testuser
CREATE EXTERNAL CONNECTION bar AS 'nodelocal://1/foo'
----

query-sql user=testuser
SHOW CREATE ALL EXTERNAL CONNECTIONS
----
pq: must be admin to run `SHOW CREATE ALL EXTERNAL CONNECTIONS

# TODO(aditymaru): Synthetic privileges do not have a concept of owners. Once they do, testuser will
# be able to run this query successfully since they are the owner of the External Connection object.
# query-sql user=testuser
# SHOW CREATE EXTERNAL CONNECTION bar
# ----

subtest end
9 changes: 9 additions & 0 deletions pkg/cloud/externalconn/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ import (
// an External Connection object. This interface should expose read-only
// methods that are required to interact with the External Connection object.
type ExternalConnection interface {
// UnredactedConnectionStatement returns a `CREATE EXTERNAL CONNECTION`
// statement that is functionally equivalent to the statement that created the
// external connection in the first place.
//
// NB: The returned string will contain unredacted secrets and should not be
// persisted.
UnredactedConnectionStatement() string
// ConnectionName returns the label of the connection.
ConnectionName() string
// ConnectionType returns the type of the connection.
ConnectionType() connectionpb.ConnectionType
// ConnectionProto returns an in-memory representation of the
Expand Down
13 changes: 12 additions & 1 deletion pkg/cloud/externalconn/connectionpb/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ func (d *ConnectionDetails) Type() ConnectionType {
case ConnectionProvider_kafka:
return TypeStorage
default:
panic(errors.AssertionFailedf("ConnectionDetails.Type called on a details with an unknown type: %T", d.Provider.String()))
panic(errors.AssertionFailedf("ConnectionDetails.Type called on a details with an unknown type: %s", d.Provider.String()))
}
}

// UnredactedURI returns the unredacted URI of the resource represented by the
// External Connection.
func (d *ConnectionDetails) UnredactedURI() string {
switch c := d.Details.(type) {
case *ConnectionDetails_SimpleURI:
return c.SimpleURI.URI
default:
panic(errors.AssertionFailedf("ConnectionDetails.UnredactedURI called on details with an unknown type: %s", d.Provider.String()))
}
}
16 changes: 16 additions & 0 deletions pkg/cloud/externalconn/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,22 @@ func (e *MutableExternalConnection) SetConnectionDetails(details connectionpb.Co
e.markDirty("connection_details")
}

// ConnectionName returns the connection_name.
func (e *MutableExternalConnection) ConnectionName() string {
return e.rec.ConnectionName
}

// UnredactedConnectionStatement implements the External Connection interface.
func (e *MutableExternalConnection) UnredactedConnectionStatement() string {
ecNode := &tree.CreateExternalConnection{
ConnectionLabelSpec: tree.LabelSpec{
Label: tree.NewDString(e.rec.ConnectionName),
},
As: tree.NewDString(e.rec.ConnectionDetails.UnredactedURI()),
}
return tree.AsString(ecNode)
}

// datumToNative is a helper to convert tree.Datum into Go native types. We
// only care about types stored in the system.external_connections table.
func datumToNative(datum tree.Datum) (interface{}, error) {
Expand Down
1 change: 1 addition & 0 deletions pkg/gen/bnf.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ BNF_SRCS = [
"//docs/generated/sql/bnf:show_cluster_setting.bnf",
"//docs/generated/sql/bnf:show_columns_stmt.bnf",
"//docs/generated/sql/bnf:show_constraints_stmt.bnf",
"//docs/generated/sql/bnf:show_create_external_connections_stmt.bnf",
"//docs/generated/sql/bnf:show_create_schedules_stmt.bnf",
"//docs/generated/sql/bnf:show_create_stmt.bnf",
"//docs/generated/sql/bnf:show_databases_stmt.bnf",
Expand Down
1 change: 1 addition & 0 deletions pkg/gen/diagrams.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ DIAGRAMS_SRCS = [
"//docs/generated/sql/bnf:show_columns.html",
"//docs/generated/sql/bnf:show_constraints.html",
"//docs/generated/sql/bnf:show_create.html",
"//docs/generated/sql/bnf:show_create_external_connections.html",
"//docs/generated/sql/bnf:show_create_schedules.html",
"//docs/generated/sql/bnf:show_databases.html",
"//docs/generated/sql/bnf:show_default_privileges.html",
Expand Down
1 change: 1 addition & 0 deletions pkg/gen/docs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ DOCS_SRCS = [
"//docs/generated/sql/bnf:show_cluster_setting.bnf",
"//docs/generated/sql/bnf:show_columns_stmt.bnf",
"//docs/generated/sql/bnf:show_constraints_stmt.bnf",
"//docs/generated/sql/bnf:show_create_external_connections_stmt.bnf",
"//docs/generated/sql/bnf:show_create_schedules_stmt.bnf",
"//docs/generated/sql/bnf:show_create_stmt.bnf",
"//docs/generated/sql/bnf:show_databases_stmt.bnf",
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ go_library(
"show_cluster_setting.go",
"show_create.go",
"show_create_clauses.go",
"show_create_external_connection.go",
"show_create_schedule.go",
"show_fingerprints.go",
"show_histogram.go",
Expand Down
3 changes: 3 additions & 0 deletions pkg/sql/opaque.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ func planOpaque(ctx context.Context, p *planner, stmt tree.Statement) (planNode,
return p.ShowTenantClusterSetting(ctx, n)
case *tree.ShowCreateSchedules:
return p.ShowCreateSchedule(ctx, n)
case *tree.ShowCreateExternalConnections:
return p.ShowCreateExternalConnection(ctx, n)
case *tree.ShowHistogram:
return p.ShowHistogram(ctx, n)
case *tree.ShowTableStats:
Expand Down Expand Up @@ -358,6 +360,7 @@ func init() {
&tree.ShowClusterSetting{},
&tree.ShowTenantClusterSetting{},
&tree.ShowCreateSchedules{},
&tree.ShowCreateExternalConnections{},
&tree.ShowHistogram{},
&tree.ShowTableStats{},
&tree.ShowTraceForSession{},
Expand Down
3 changes: 3 additions & 0 deletions pkg/sql/parser/help_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,9 @@ func TestContextualHelp(t *testing.T) {
{`SHOW CREATE SCHEDULE blah ??`, `SHOW CREATE SCHEDULES`},
{`SHOW CREATE ALL SCHEDULES ??`, `SHOW CREATE SCHEDULES`},

{`SHOW CREATE EXTERNAL CONNECTION blah ??`, `SHOW CREATE EXTERNAL CONNECTIONS`},
{`SHOW CREATE ALL EXTERNAL CONNECTIONS ??`, `SHOW CREATE EXTERNAL CONNECTIONS`},

{`SHOW DATABASES ??`, `SHOW DATABASES`},

{`SHOW DEFAULT PRIVILEGES ??`, `SHOW DEFAULT PRIVILEGES`},
Expand Down
Loading

0 comments on commit 41e20ce

Please sign in to comment.