Skip to content

Commit

Permalink
feat: add functional support for subgroups
Browse files Browse the repository at this point in the history
Refactor permission engine to use the new keycloak client functionality
which adds support for subgroups, and refactor session logic to use the
new permission engine.
  • Loading branch information
smlx committed Oct 11, 2024
1 parent 3b6b802 commit 8e0ffd0
Show file tree
Hide file tree
Showing 15 changed files with 608 additions and 725 deletions.
18 changes: 9 additions & 9 deletions cmd/ssh-portal-api/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,14 @@ func (cmd *ServeCmd) Run(log *slog.Logger) error {
// get main process context, which cancels on SIGTERM
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM)
defer stop()
// init RBAC permission engine
var p *rbac.Permission
if cmd.BlockDeveloperSSH {
p = rbac.NewPermission(rbac.BlockDeveloperSSH())
} else {
p = rbac.NewPermission()
}
// init lagoon DB client
dbConf := mysql.NewConfig()
dbConf.Addr = cmd.APIDBAddress
dbConf.DBName = cmd.APIDBDatabase
dbConf.Net = "tcp"
dbConf.Passwd = cmd.APIDBPassword
dbConf.User = cmd.APIDBUsername
l, err := lagoondb.NewClient(ctx, dbConf.FormatDSN())
ldb, err := lagoondb.NewClient(ctx, dbConf.FormatDSN())
if err != nil {
return fmt.Errorf("couldn't init lagoondb client: %v", err)
}
Expand All @@ -66,14 +59,21 @@ func (cmd *ServeCmd) Run(log *slog.Logger) error {
if err != nil {
return fmt.Errorf("couldn't init keycloak client: %v", err)
}
// init RBAC permission engine
var p *rbac.Permission
if cmd.BlockDeveloperSSH {
p = rbac.NewPermission(k, ldb, rbac.BlockDeveloperSSH())
} else {
p = rbac.NewPermission(k, ldb)
}
// set up goroutine handler
eg, ctx := errgroup.WithContext(ctx)
// start the metrics server
metrics.Serve(ctx, eg, metricsPort)
// start serving SSH token requests
eg.Go(func() error {
// start serving NATS requests
return sshportalapi.ServeNATS(ctx, stop, log, p, l, k, cmd.NATSURL)
return sshportalapi.ServeNATS(ctx, stop, log, p, ldb, cmd.NATSURL)
})
return eg.Wait()
}
17 changes: 8 additions & 9 deletions cmd/ssh-token/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,6 @@ func (cmd *ServeCmd) Run(log *slog.Logger) error {
// get main process context, which cancels on SIGTERM
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM)
defer stop()
// init RBAC permission engine
var p *rbac.Permission
if cmd.BlockDeveloperSSH {
p = rbac.NewPermission(rbac.BlockDeveloperSSH())
} else {
p = rbac.NewPermission()
}
// init lagoon DB client
dbConf := mysql.NewConfig()
dbConf.Addr = cmd.APIDBAddress
Expand Down Expand Up @@ -81,6 +74,13 @@ func (cmd *ServeCmd) Run(log *slog.Logger) error {
if err != nil {
return fmt.Errorf("couldn't init keycloak permission client: %v", err)
}
// init RBAC permission engine
var p *rbac.Permission
if cmd.BlockDeveloperSSH {
p = rbac.NewPermission(keycloakPermission, ldb, rbac.BlockDeveloperSSH())
} else {
p = rbac.NewPermission(keycloakPermission, ldb)
}
// start listening on TCP port
l, err := net.Listen("tcp", fmt.Sprintf(":%d", cmd.SSHServerPort))
if err != nil {
Expand All @@ -101,8 +101,7 @@ func (cmd *ServeCmd) Run(log *slog.Logger) error {
metrics.Serve(ctx, eg, metricsPort)
// start serving SSH token requests
eg.Go(func() error {
return sshtoken.Serve(ctx, log, l, p, ldb, keycloakToken, keycloakPermission,
hostkeys)
return sshtoken.Serve(ctx, log, l, p, ldb, keycloakToken, hostkeys)
})
return eg.Wait()
}
75 changes: 0 additions & 75 deletions internal/lagoon/groupnameprojectids.go

This file was deleted.

89 changes: 0 additions & 89 deletions internal/lagoon/groupnameprojectids_test.go

This file was deleted.

58 changes: 26 additions & 32 deletions internal/lagoondb/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,6 @@ type User struct {
UUID *uuid.UUID `db:"uuid"`
}

// groupProjectMapping maps Lagoon group ID to project ID.
// This type is only used for database unmarshalling.
type groupProjectMapping struct {
GroupID string `db:"group_id"`
ProjectID int `db:"project_id"`
}

// ErrNoResult is returned by client methods if there is no result.
var ErrNoResult = errors.New("no rows in result set")

Expand Down Expand Up @@ -144,31 +137,6 @@ func (c *Client) SSHEndpointByEnvironmentID(ctx context.Context,
return ssh.Host, ssh.Port, nil
}

// GroupIDProjectIDsMap returns a map of Group (UU)IDs to Project IDs.
// This denotes Project Group membership in Lagoon.
func (c *Client) GroupIDProjectIDsMap(
ctx context.Context,
) (map[string][]int, error) {
var gpms []groupProjectMapping
err := c.db.SelectContext(ctx, &gpms,
`SELECT group_id, project_id `+
`FROM kc_group_projects`)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrNoResult
}
return nil, err
}
groupIDProjectIDsMap := map[string][]int{}
// no need to check for duplicates here since the table has:
// UNIQUE KEY `group_project` (`group_id`,`project_id`)
for _, gpm := range gpms {
groupIDProjectIDsMap[gpm.GroupID] =
append(groupIDProjectIDsMap[gpm.GroupID], gpm.ProjectID)
}
return groupIDProjectIDsMap, nil
}

// SSHKeyUsed sets the last_used attribute of the ssh key identified by the
// given fingerprint to used.
//
Expand All @@ -182,6 +150,7 @@ func (c *Client) SSHKeyUsed(
// set up tracing
ctx, span := otel.Tracer(pkgName).Start(ctx, "SSHKeyUsed")
defer span.End()
// run query
_, err := c.db.ExecContext(ctx,
`UPDATE ssh_key `+
`SET last_used = ? `+
Expand All @@ -194,3 +163,28 @@ func (c *Client) SSHKeyUsed(
}
return nil
}

// ProjectGroupIDs returns a slice of Group (UU)IDs of which the project
// identified by the given projectID is a member.
func (c *Client) ProjectGroupIDs(
ctx context.Context,
projectID int,
) ([]uuid.UUID, error) {
// set up tracing
ctx, span := otel.Tracer(pkgName).Start(ctx, "ProjectGroupIDs")
defer span.End()
// run query
var gids []uuid.UUID
err := c.db.SelectContext(ctx, &gids,
`SELECT group_id `+
`FROM kc_group_projects `+
`WHERE project_id = ?`,
projectID)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrNoResult
}
return nil, err
}
return gids, nil
}
Loading

0 comments on commit 8e0ffd0

Please sign in to comment.