Skip to content
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
20 changes: 10 additions & 10 deletions internal/postgres/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,37 +34,37 @@ var (
revokeUsage = `REVOKE USAGE ON SCHEMA $schema FROM cloudsqliamuser;`
)

func PrepareAccess(ctx context.Context, appName string, namespace flag.Namespace, cluster flag.Context, schema string, allPrivs bool, out *naistrix.OutputWriter) error {
func PrepareAccess(ctx context.Context, appName string, fl *flag.Prepare, out *naistrix.OutputWriter) error {
// Get secret values (access is logged for audit purposes)
if _, err := GetSecretValues(ctx, appName, namespace, cluster, ReasonPrepareAccess, out); err != nil {
if _, err := GetSecretValues(ctx, appName, fl.Postgres, ReasonPrepareAccess, out); err != nil {
return err
}

prependUsageIfNotPublic := func(statement string) string {
if schema != "public" {
if fl.Schema != "public" {
return grantUsage + "\n" + statement
}
return statement
}

if allPrivs {
return sqlExecAsAppUser(ctx, appName, namespace, cluster, schema, prependUsageIfNotPublic(grantAllPrivs))
if fl.AllPrivileges {
return sqlExecAsAppUser(ctx, appName, fl.Namespace, fl.Context, fl.Schema, prependUsageIfNotPublic(grantAllPrivs))
} else {
return sqlExecAsAppUser(ctx, appName, namespace, cluster, schema, prependUsageIfNotPublic(grantSelectPrivs))
return sqlExecAsAppUser(ctx, appName, fl.Namespace, fl.Context, fl.Schema, prependUsageIfNotPublic(grantSelectPrivs))
}
}

func RevokeAccess(ctx context.Context, appName string, namespace flag.Namespace, cluster flag.Context, schema string, out *naistrix.OutputWriter) error {
func RevokeAccess(ctx context.Context, appName string, fl *flag.Revoke, out *naistrix.OutputWriter) error {
// Get secret values (access is logged for audit purposes)
if _, err := GetSecretValues(ctx, appName, namespace, cluster, ReasonRevokeAccess, out); err != nil {
if _, err := GetSecretValues(ctx, appName, fl.Postgres, ReasonRevokeAccess, out); err != nil {
return err
}

q := revokeAllPrivs
if schema != "public" {
if fl.Schema != "public" {
q += "\n" + revokeUsage
}
return sqlExecAsAppUser(ctx, appName, namespace, cluster, schema, q)
return sqlExecAsAppUser(ctx, appName, fl.Namespace, fl.Context, fl.Schema, q)
}

func sqlExecAsAppUser(ctx context.Context, appName string, namespace flag.Namespace, cluster flag.Context, schema, statement string) error {
Expand Down
20 changes: 10 additions & 10 deletions internal/postgres/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
)

func EnableAuditLogging(ctx context.Context, appName string, cluster flag.Context, namespace flag.Namespace, out *naistrix.OutputWriter) error {
func EnableAuditLogging(ctx context.Context, appName string, fl *flag.EnableAudit, out *naistrix.OutputWriter) error {
// Get secret values (access is logged for audit purposes)
if _, err := GetSecretValues(ctx, appName, namespace, cluster, ReasonEnableAudit, out); err != nil {
if _, err := GetSecretValues(ctx, appName, fl.Postgres, ReasonEnableAudit, out); err != nil {
return err
}
return enableAuditAsAppUser(ctx, appName, namespace, cluster, out)
return enableAuditAsAppUser(ctx, appName, fl.Namespace, fl.Context, out)
}

func VerifyAuditLogging(ctx context.Context, appName string, cluster flag.Context, namespace flag.Namespace, out *naistrix.OutputWriter) error {
func VerifyAuditLogging(ctx context.Context, appName string, fl *flag.VerifyAudit, out *naistrix.OutputWriter) error {
// Get secret values (access is logged for audit purposes)
if _, err := GetSecretValues(ctx, appName, namespace, cluster, ReasonVerifyAudit, out); err != nil {
if _, err := GetSecretValues(ctx, appName, fl.Postgres, ReasonVerifyAudit, out); err != nil {
return err
}
_, err := verifyAuditAsAppUser(ctx, appName, namespace, cluster, out)
_, err := verifyAuditAsAppUser(ctx, appName, fl.Namespace, fl.Context, out)
return err
}

Expand Down Expand Up @@ -166,23 +166,23 @@ func getDBFlags(ctx context.Context, info *CloudSQLDBInfo) (map[string]string, e
return dbFlags, fmt.Errorf("GetDBInstance: expected one sqlinstance for app %q in %q, got %d", info.appName, info.namespace, len(sqlInstances.Items))
}

spec, ok := sqlInstances.Items[0].Object["spec"].(map[string]interface{})
spec, ok := sqlInstances.Items[0].Object["spec"].(map[string]any)
if !ok {
return dbFlags, fmt.Errorf("GetDBInstance: error accessing spec for app %q in %q", info.appName, info.namespace)
}

settings, ok := spec["settings"].(map[string]interface{})
settings, ok := spec["settings"].(map[string]any)
if !ok {
return dbFlags, fmt.Errorf("GetDBInstance: error accessing settings for app %q in %q", info.appName, info.namespace)
}

databaseFlags, ok := settings["databaseFlags"].([]interface{})
databaseFlags, ok := settings["databaseFlags"].([]any)
if !ok {
return dbFlags, fmt.Errorf("GetDBInstance: error accessing databaseFlags for app %q in %q", info.appName, info.namespace)
}

for _, flag := range databaseFlags {
f, ok := flag.(map[string]interface{})
f, ok := flag.(map[string]any)
if !ok {
return dbFlags, fmt.Errorf("GetDBInstance: error accessing databaseFlags for app %q in %q", info.appName, info.namespace)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/postgres/command/enable_audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func enableAuditCommand(parentFlags *flag.Postgres) *naistrix.Command {
},
Flags: flags,
RunFunc: func(ctx context.Context, args *naistrix.Arguments, out *naistrix.OutputWriter) error {
err := postgres.EnableAuditLogging(ctx, args.Get("app_name"), flags.Context, flags.Namespace, out)
err := postgres.EnableAuditLogging(ctx, args.Get("app_name"), flags, out)
if err != nil {
metric.CreateAndIncreaseCounter(ctx, "enable_audit_logging_error")
}
Expand Down
24 changes: 24 additions & 0 deletions internal/postgres/command/flag/environment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package flag

import (
"context"
"fmt"

"github.com/nais/cli/internal/naisapi"
"github.com/nais/naistrix"
)

type Environment string

func (e *Environment) AutoComplete(ctx context.Context, args *naistrix.Arguments, str string, flags any) ([]string, string) {
return autoCompleteEnvironments(ctx)
}

func autoCompleteEnvironments(ctx context.Context) ([]string, string) {
envs, err := naisapi.GetAllEnvironments(ctx)
if err != nil {
return nil, fmt.Sprintf("Failed to fetch environments for auto-completion: %v", err)
}

return envs, "Available environments"
}
7 changes: 4 additions & 3 deletions internal/postgres/command/flag/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import "github.com/nais/cli/internal/flags"

type Postgres struct {
*flags.GlobalFlags
Namespace Namespace `name:"namespace" short:"n" usage:"The kubernetes |NAMESPACE| to use. Defaults to current namespace."`
Context Context `name:"context" short:"c" usage:"The kubeconfig |CONTEXT| to use. Defaults to current context."`
Reason string `name:"reason" short:"r" usage:"Justification for accessing the database. Required for audit logging."`
Namespace Namespace `name:"namespace" short:"n" usage:"The kubernetes |NAMESPACE| to use. Defaults to current namespace."`
Context Context `name:"context" short:"c" usage:"The kubeconfig |CONTEXT| to use. Defaults to current context."`
Environment Environment `name:"environment" short:"e" usage:"The |ENVIRONMENT| to use. Defaults to same as context."`
Reason string `name:"reason" short:"r" usage:"Justification for accessing the database. Required for audit logging."`
}

type Migrate struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/postgres/command/password.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func passwordCommand(parentFlags *flag.Postgres) *naistrix.Command {
{Name: "app_name"},
},
RunFunc: func(ctx context.Context, args *naistrix.Arguments, out *naistrix.OutputWriter) error {
return postgres.RotatePassword(ctx, args.Get("app_name"), flags.Context, flags.Namespace, out)
return postgres.RotatePassword(ctx, args.Get("app_name"), flags, out)
},
},
},
Expand Down
1 change: 1 addition & 0 deletions internal/postgres/command/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func Postgres(parentFlags *flags.GlobalFlags) *naistrix.Command {
GlobalFlags: parentFlags,
Namespace: flag.Namespace(defaultNamespace),
Context: flag.Context(defaultContext),
Environment: flag.Environment(defaultContext),
}

return &naistrix.Command{
Expand Down
15 changes: 4 additions & 11 deletions internal/postgres/command/prepare.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package command

import (
"bufio"
"context"
"fmt"
"os"
"strings"

_ "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/postgres"
"github.com/MakeNowJust/heredoc/v2"
"github.com/nais/cli/internal/postgres"
"github.com/nais/cli/internal/postgres/command/flag"
"github.com/nais/naistrix"
"github.com/pterm/pterm"
)

func prepareCommand(parentFlags *flag.Postgres) *naistrix.Command {
Expand All @@ -35,17 +33,12 @@ func prepareCommand(parentFlags *flag.Postgres) *naistrix.Command {
},
Flags: flags,
RunFunc: func(ctx context.Context, args *naistrix.Arguments, out *naistrix.OutputWriter) error {
out.Println("", "Are you sure you want to continue (y/N): ")
i, err := bufio.NewReader(os.Stdin).ReadString('\n')
if err != nil {
return fmt.Errorf("failed to read input: %w", err)
}

if !strings.EqualFold(strings.TrimSpace(i), "y") {
result, _ := pterm.DefaultInteractiveConfirm.Show("Are you sure you want to continue?")
if !result {
return fmt.Errorf("cancelled by user")
}

return postgres.PrepareAccess(ctx, args.Get("app_name"), flags.Namespace, flags.Context, flags.Schema, flags.AllPrivileges, out)
return postgres.PrepareAccess(ctx, args.Get("app_name"), flags, out)
},
}
}
2 changes: 1 addition & 1 deletion internal/postgres/command/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func proxyCommand(parentFlags *flag.Postgres) *naistrix.Command {
},
Flags: flags,
RunFunc: func(ctx context.Context, args *naistrix.Arguments, out *naistrix.OutputWriter) error {
return postgres.RunProxy(ctx, args.Get("app_name"), flags.Context, flags.Namespace, flags.Host, flags.Port, flags.IsVerbose(), flags.Reason, out)
return postgres.RunProxy(ctx, args.Get("app_name"), flags, out)
},
}
}
2 changes: 1 addition & 1 deletion internal/postgres/command/psql.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func psqlCommand(parentFlags *flag.Postgres) *naistrix.Command {
},
Flags: flags,
RunFunc: func(ctx context.Context, args *naistrix.Arguments, out *naistrix.OutputWriter) error {
return postgres.RunPSQL(ctx, args.Get("app_name"), flags.Context, flags.Namespace, flags.Reason, out)
return postgres.RunPSQL(ctx, args.Get("app_name"), flags, out)
},
}
}
12 changes: 4 additions & 8 deletions internal/postgres/command/revoke.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package command

import (
"bufio"
"context"
"fmt"
"os"
"strings"

_ "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/postgres"
"github.com/MakeNowJust/heredoc/v2"
"github.com/nais/cli/internal/postgres"
"github.com/nais/cli/internal/postgres/command/flag"
"github.com/nais/naistrix"
"github.com/pterm/pterm"
)

func revokeCommand(parentFlags *flag.Postgres) *naistrix.Command {
Expand All @@ -35,14 +33,12 @@ func revokeCommand(parentFlags *flag.Postgres) *naistrix.Command {
},
Flags: flags,
RunFunc: func(ctx context.Context, args *naistrix.Arguments, out *naistrix.OutputWriter) error {
out.Println("", "Are you sure you want to continue (y/N): ")
input := bufio.NewScanner(os.Stdin)
input.Scan()
if !strings.EqualFold(strings.TrimSpace(input.Text()), "y") {
result, _ := pterm.DefaultInteractiveConfirm.Show("Are you sure you want to continue?")
if !result {
return fmt.Errorf("cancelled by user")
}

return postgres.RevokeAccess(ctx, args.Get("app_name"), flags.Namespace, flags.Context, flags.Schema, out)
return postgres.RevokeAccess(ctx, args.Get("app_name"), flags, out)
},
}
}
6 changes: 3 additions & 3 deletions internal/postgres/command/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func addCommand(parentFlags *flag.User) *naistrix.Command {
},
Flags: userAddFlags,
RunFunc: func(ctx context.Context, args *naistrix.Arguments, out *naistrix.OutputWriter) error {
return postgres.AddUser(ctx, args.Get("app_name"), args.Get("username"), args.Get("password"), userAddFlags.Context, userAddFlags.Namespace, userAddFlags.Privilege, out)
return postgres.AddUser(ctx, args.Get("app_name"), args.Get("username"), args.Get("password"), userAddFlags, out)
},
}
}
Expand All @@ -53,7 +53,7 @@ func listCommand(parentFlags *flag.User) *naistrix.Command {
},
Flags: flags,
RunFunc: func(ctx context.Context, args *naistrix.Arguments, out *naistrix.OutputWriter) error {
return postgres.ListUsers(ctx, args.Get("app_name"), flags.Context, flags.Namespace, out)
return postgres.ListUsers(ctx, args.Get("app_name"), flags, out)
},
}
}
Expand All @@ -70,7 +70,7 @@ func dropCommand(parentFlags *flag.User) *naistrix.Command {
},
Flags: flags,
RunFunc: func(ctx context.Context, args *naistrix.Arguments, out *naistrix.OutputWriter) error {
return postgres.DropUser(ctx, args.Get("app_name"), args.Get("username"), flags.Context, flags.Namespace, out)
return postgres.DropUser(ctx, args.Get("app_name"), args.Get("username"), flags, out)
},
}
}
2 changes: 1 addition & 1 deletion internal/postgres/command/verify_audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func verifyAuditCommand(parentFlags *flag.Postgres) *naistrix.Command {
},
Flags: flags,
RunFunc: func(ctx context.Context, args *naistrix.Arguments, out *naistrix.OutputWriter) error {
err := postgres.VerifyAuditLogging(ctx, args.Get("app_name"), flags.Context, flags.Namespace, out)
err := postgres.VerifyAuditLogging(ctx, args.Get("app_name"), flags, out)
if err != nil {
metric.CreateAndIncreaseCounter(ctx, "verify_audit_logging_error")
}
Expand Down
24 changes: 12 additions & 12 deletions internal/postgres/iam.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,13 @@ func formatCondition(expr, title string) string {
return fmt.Sprintf("expression=%v,title=%v", expr, title)
}

func ListUsers(ctx context.Context, appName string, cluster flag.Context, namespace flag.Namespace, out *naistrix.OutputWriter) error {
func ListUsers(ctx context.Context, appName string, fl *flag.UserList, out *naistrix.OutputWriter) error {
// Get secret values (access is logged for audit purposes)
if _, err := GetSecretValues(ctx, appName, namespace, cluster, ReasonListUsers, out); err != nil {
if _, err := GetSecretValues(ctx, appName, fl.Postgres, ReasonListUsers, out); err != nil {
return err
}

dbInfo, err := NewDBInfo(ctx, appName, namespace, cluster)
dbInfo, err := NewDBInfo(ctx, appName, fl.Namespace, fl.Context)
if err != nil {
return err
}
Expand Down Expand Up @@ -255,18 +255,18 @@ func ListUsers(ctx context.Context, appName string, cluster flag.Context, namesp
return err
}

func AddUser(ctx context.Context, appName, username, password string, cluster flag.Context, namespace flag.Namespace, privilege string, out *naistrix.OutputWriter) error {
err := validateSQLVariables(username, password, privilege)
func AddUser(ctx context.Context, appName, username, password string, fl *flag.UserAdd, out *naistrix.OutputWriter) error {
err := validateSQLVariables(username, password, fl.Privilege)
if err != nil {
return err
}

// Get secret values (access is logged for audit purposes)
if _, err := GetSecretValues(ctx, appName, namespace, cluster, ReasonAddUser, out); err != nil {
if _, err := GetSecretValues(ctx, appName, fl.Postgres, ReasonAddUser, out); err != nil {
return err
}

dbInfo, err := NewDBInfo(ctx, appName, namespace, cluster)
dbInfo, err := NewDBInfo(ctx, appName, fl.Namespace, fl.Context)
if err != nil {
return err
}
Expand All @@ -287,26 +287,26 @@ func AddUser(ctx context.Context, appName, username, password string, cluster fl
}
out.Printf("Created user: %v", username)

_, err = db.ExecContext(ctx, fmt.Sprintf(`alter default privileges in schema public grant %v on tables to %q;`, privilege, username))
_, err = db.ExecContext(ctx, fmt.Sprintf(`alter default privileges in schema public grant %v on tables to %q;`, fl.Privilege, username))
if err != nil {
return formatInvalidGrantError(err)
}

_, err = db.ExecContext(ctx, fmt.Sprintf(`grant %v on all tables in schema public to %q;`, privilege, username))
_, err = db.ExecContext(ctx, fmt.Sprintf(`grant %v on all tables in schema public to %q;`, fl.Privilege, username))
if err != nil {
return formatInvalidGrantError(err)
}

return nil
}

func DropUser(ctx context.Context, appName string, username string, cluster flag.Context, namespace flag.Namespace, out *naistrix.OutputWriter) error {
func DropUser(ctx context.Context, appName string, username string, fl *flag.UserDrop, out *naistrix.OutputWriter) error {
// Get secret values (access is logged for audit purposes)
if _, err := GetSecretValues(ctx, appName, namespace, cluster, ReasonDropUser, out); err != nil {
if _, err := GetSecretValues(ctx, appName, fl.Postgres, ReasonDropUser, out); err != nil {
return err
}

dbInfo, err := NewDBInfo(ctx, appName, namespace, cluster)
dbInfo, err := NewDBInfo(ctx, appName, fl.Namespace, fl.Context)
if err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions internal/postgres/password.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func RotatePassword(ctx context.Context, appName string, cluster flag.Context, namespace flag.Namespace, out *naistrix.OutputWriter) error {
func RotatePassword(ctx context.Context, appName string, fl *flag.Password, out *naistrix.OutputWriter) error {
// Get secret values (access is logged for audit purposes)
if _, err := GetSecretValues(ctx, appName, namespace, cluster, ReasonPasswordRotate, out); err != nil {
if _, err := GetSecretValues(ctx, appName, fl.Postgres, ReasonPasswordRotate, out); err != nil {
return err
}

dbInfo, err := NewDBInfo(ctx, appName, namespace, cluster)
dbInfo, err := NewDBInfo(ctx, appName, fl.Namespace, fl.Context)
if err != nil {
return err
}
Expand Down
Loading