Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit dac9c45

Browse files
committed
Merge branch '124-restricted-user' into 'master'
feat: create a restricted user (joe#124) # Description Allow creating a user with restricted permissions in order to protect from stealing the data (massively): - add a new API parameter `restricted` to create a user with restricted permissions - support a new parameter in the Database Lab CLI - define a special query template to create a user with limited permissions # Related issue joe#124 See merge request postgres-ai/database-lab!250
2 parents 4581210 + 86b59c5 commit dac9c45

File tree

8 files changed

+81
-13
lines changed

8 files changed

+81
-13
lines changed

api/swagger-spec/dblab_server_swagger.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,9 @@ definitions:
386386
type: "string"
387387
password:
388388
type: "string"
389+
restricted:
390+
type: "boolean"
391+
default: false
389392

390393
UpdateClone:
391394
type: "object"

cmd/cli/commands/clone/actions.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ func create(cliCtx *cli.Context) error {
5555
ID: cliCtx.String("id"),
5656
Protected: cliCtx.Bool("protected"),
5757
DB: &types.DatabaseRequest{
58-
Username: cliCtx.String("username"),
59-
Password: cliCtx.String("password"),
58+
Username: cliCtx.String("username"),
59+
Password: cliCtx.String("password"),
60+
Restricted: cliCtx.Bool("restricted"),
6061
},
6162
}
6263

cmd/cli/commands/clone/command_list.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ func CommandList() []*cli.Command {
4343
Usage: "database password",
4444
Required: true,
4545
},
46+
&cli.BoolFlag{
47+
Name: "restricted",
48+
Usage: "create a user with restricted permissions",
49+
},
4650
&cli.StringFlag{
4751
Name: "id",
4852
Usage: "clone ID (optional)",

pkg/client/dblabapi/types/clone.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ type CloneUpdateRequest struct {
2121

2222
// DatabaseRequest represents database params of a clone request.
2323
type DatabaseRequest struct {
24-
Username string `json:"username"`
25-
Password string `json:"password"`
24+
Username string `json:"username"`
25+
Password string `json:"password"`
26+
Restricted bool `json:"restricted"`
2627
}
2728

2829
// SnapshotCloneFieldRequest represents snapshot params of a create request.

pkg/services/cloning/mode_base.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func (c *baseCloning) CreateClone(cloneRequest *types.CloneCreateRequest) (*mode
140140
c.setWrapper(clone.ID, w)
141141

142142
go func() {
143-
session, err := c.provision.StartSession(w.username, w.password, w.snapshot.ID, cloneRequest.ExtraConf)
143+
session, err := c.provision.StartSession(w.username, w.password, w.snapshot.ID, cloneRequest.DB.Restricted, cloneRequest.ExtraConf)
144144
if err != nil {
145145
// TODO(anatoly): Empty room case.
146146
log.Errf("Failed to start session: %v.", err)

pkg/services/provision/databases/postgres/postgres_mgmt.go

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,14 @@ func ResetAllPasswords(c *resources.AppConfig, whitelistUsers []string) error {
7070
}
7171

7272
// CreateUser defines a method for creation of Postgres user.
73-
func CreateUser(c *resources.AppConfig, username string, password string) error {
74-
query := fmt.Sprintf("create user \"%s\" with password '%s' login superuser;",
75-
username, password)
73+
func CreateUser(c *resources.AppConfig, username, password string, restricted bool) error {
74+
var query string
75+
76+
if restricted {
77+
query = restrictedUserQuery(username, password, c.DB.DBName)
78+
} else {
79+
query = superuserQuery(username, password)
80+
}
7681

7782
out, err := runSimpleSQL(query, c)
7883
if err != nil {
@@ -83,3 +88,55 @@ func CreateUser(c *resources.AppConfig, username string, password string) error
8388

8489
return nil
8590
}
91+
92+
func superuserQuery(username, password string) string {
93+
return fmt.Sprintf(`create user "%s" with password '%s' login superuser;`, username, password)
94+
}
95+
96+
const restrictedTemplate = `
97+
-- create new user
98+
create user %[1]s with password '%s' createdb;
99+
100+
-- grant all privileges in the database
101+
grant all privileges on database %s to %[1]s;
102+
103+
-- grant all on all objects in all schemas in the database
104+
do $$
105+
begin
106+
-- grant usage on all schemas in the database
107+
execute (
108+
select string_agg(format('grant usage on schema %%I to %[1]s', nspname), '; ')
109+
from pg_namespace
110+
where nspname <> 'information_schema'
111+
and nspname not like 'pg\_%%'
112+
);
113+
114+
-- grant all on all tables in all schemas in database
115+
execute (
116+
select string_agg(format('grant all on all tables in schema %%I to %[1]s', nspname), '; ')
117+
from pg_namespace
118+
where nspname <> 'information_schema'
119+
and nspname not like 'pg\_%%'
120+
);
121+
122+
-- grant all on all sequences in all custom schemas in the database
123+
execute (
124+
select string_agg(format('grant all on all sequences in schema %%I to %[1]s', nspname), '; ')
125+
from pg_namespace
126+
where nspname <> 'information_schema'
127+
and nspname not like 'pg\_%%'
128+
);
129+
130+
-- grant all on all functions in all schemas in the database
131+
execute (
132+
select string_agg(format('grant all on all functions in schema %%I to %[1]s', nspname), '; ')
133+
from pg_namespace
134+
where nspname <> 'information_schema'
135+
and nspname not like 'pg\_%%'
136+
);
137+
end $$;
138+
`
139+
140+
func restrictedUserQuery(username, password, database string) string {
141+
return fmt.Sprintf(restrictedTemplate, username, password, database)
142+
}

pkg/services/provision/mode_local.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func (p *Provisioner) Reload(cfg Config, dbCfg resources.DB) {
143143
}
144144

145145
// StartSession starts a new session.
146-
func (p *Provisioner) StartSession(username, password, snapshotID string,
146+
func (p *Provisioner) StartSession(username, password, snapshotID string, restricted bool,
147147
extraConfig map[string]string) (*resources.Session, error) {
148148
snapshotID, err := p.getSnapshotID(snapshotID)
149149
if err != nil {
@@ -181,7 +181,7 @@ func (p *Provisioner) StartSession(username, password, snapshotID string,
181181
return nil, errors.Wrap(err, "failed to start a container")
182182
}
183183

184-
if err := p.prepareDB(username, password, appConfig); err != nil {
184+
if err := p.prepareDB(appConfig, username, password, restricted); err != nil {
185185
return nil, errors.Wrap(err, "failed to prepare a database")
186186
}
187187

@@ -195,6 +195,7 @@ func (p *Provisioner) StartSession(username, password, snapshotID string,
195195
SocketHost: appConfig.Host,
196196
EphemeralUser: username,
197197
EphemeralPassword: password,
198+
Restricted: restricted,
198199
ExtraConfig: extraConfig,
199200
}
200201

@@ -264,7 +265,7 @@ func (p *Provisioner) ResetSession(session *resources.Session, snapshotID string
264265
return errors.Wrap(err, "failed to start a container")
265266
}
266267

267-
if err := p.prepareDB(session.EphemeralUser, session.EphemeralPassword, appConfig); err != nil {
268+
if err := p.prepareDB(appConfig, session.EphemeralUser, session.EphemeralPassword, session.Restricted); err != nil {
268269
return errors.Wrap(err, "failed to prepare a database")
269270
}
270271

@@ -565,7 +566,7 @@ func (p *Provisioner) scanCSVLogFile(ctx context.Context, filename string, avail
565566
}
566567
}
567568

568-
func (p *Provisioner) prepareDB(username, password string, pgConf *resources.AppConfig) error {
569+
func (p *Provisioner) prepareDB(pgConf *resources.AppConfig, username, password string, restricted bool) error {
569570
if !p.config.KeepUserPasswords {
570571
whitelist := []string{p.dbCfg.Username}
571572

@@ -574,7 +575,7 @@ func (p *Provisioner) prepareDB(username, password string, pgConf *resources.App
574575
}
575576
}
576577

577-
if err := postgres.CreateUser(pgConf, username, password); err != nil {
578+
if err := postgres.CreateUser(pgConf, username, password, restricted); err != nil {
578579
return errors.Wrap(err, "failed to create user")
579580
}
580581

pkg/services/provision/resources/resources.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type Session struct {
2323
// For user-defined username and password.
2424
EphemeralUser string
2525
EphemeralPassword string
26+
Restricted bool
2627

2728
ExtraConfig map[string]string
2829
}

0 commit comments

Comments
 (0)