Skip to content

Commit

Permalink
handle all authorization on node
Browse files Browse the repository at this point in the history
  • Loading branch information
djelusic committed Mar 3, 2022
1 parent 33cb804 commit 047679a
Show file tree
Hide file tree
Showing 21 changed files with 81 additions and 245 deletions.
3 changes: 1 addition & 2 deletions cli/cmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,7 @@ func bindAwsInstallFlags(cmd *cobra.Command, a *controller.SetupArgs) {
cmd.Flags().BoolVar(&a.UseEnv, "aws-env", false, "Use AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION environment variables for AWS authentication")
cmd.Flags().StringVar(&a.Profile, "aws-profile", "", "Use the given profile for AWS authentication")
cmd.Flags().BoolVar(&a.DryRun, "dry-run", false, "Don't start install/uninstall just show what credentials will be used")
cmd.Flags().StringVar(&a.GithubUser, "github-user", "", "The GitHub user that owns the node")
cmd.Flags().StringVar(&a.GithubOrg, "github-org", "", "The GitHub organization that owns the node")
cmd.Flags().StringVar(&a.GithubID, "github-id", "", "The GitHub user that owns the node")
}

func showAwsDryRunInfo(a *controller.SetupArgs) {
Expand Down
1 change: 0 additions & 1 deletion cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ func root() *cobra.Command {
//examples.NewArgsCommand,
examples.NewGithubAuthCommand,
examples.NewUserCommand,
examples.NewProjectCommand,
examples.NewLogoutCommand,
}
for _, sub := range subCommands {
Expand Down
66 changes: 18 additions & 48 deletions cli/controller/examples/node_example.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/mantil-io/mantil/cli/controller/invoke"
"github.com/mantil-io/mantil/cli/ui"
"github.com/mantil-io/mantil/domain"
"github.com/mantil-io/mantil/node/dto"
"github.com/spf13/cobra"
)

Expand All @@ -19,17 +20,14 @@ func NewUserCommand() *cobra.Command {
return cmd
}

type AddUserRequest struct {
Username string `json:"username"`
}

func NewUserAddCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "add",
Hidden: true,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
node := cmd.Flag("node").Value.String()
user := cmd.Flag("github-username").Value.String()
role := cmd.Flag("role").Value.String()
n, err := findNode(node)
if err != nil {
return err
Expand All @@ -38,57 +36,29 @@ func NewUserAddCommand() *cobra.Command {
if err != nil {
return err
}
return i.Do("node/addUser", &AddUserRequest{
Username: args[0],
}, nil)
},
}
cmd.Flags().StringP("node", "", domain.DefaultNodeName, "")
return cmd
}

func NewProjectCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "project",
Hidden: true,
}
cmd.AddCommand(NewProjectAddCommand())
return cmd
}

type AddProjectRequest struct {
Name string `json:"name"`
Repo string `json:"repo"`
}

func NewProjectAddCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "add",
Hidden: true,
RunE: func(cmd *cobra.Command, args []string) error {
node := cmd.Flag("node").Value.String()
name := cmd.Flag("name").Value.String()
repo := cmd.Flag("repo").Value.String()
if node == "" || name == "" {
return fmt.Errorf("must specify node and project name")
}
n, err := findNode(node)
if err != nil {
return err
resolveRole := func(r string) (domain.Role, error) {
switch r {
case "admin":
return domain.Owner, nil
case "user":
return domain.Member, nil
default:
return -1, fmt.Errorf("unknown role")
}
}
i, err := nodeInvoker(n)
r, err := resolveRole(role)
if err != nil {
return err
}
return i.Do("node/addProject", &AddProjectRequest{
Name: name,
Repo: repo,
return i.Do("node/addUser", &dto.AddUserRequest{
Username: user,
Role: r,
}, nil)
},
}
cmd.Flags().StringP("node", "", domain.DefaultNodeName, "")
cmd.Flags().StringP("name", "", "", "the name of the project")
cmd.Flags().StringP("repo", "", "", "the project's github repo")
cmd.Flags().StringP("github-username", "", "", "")
cmd.Flags().StringP("role", "", "user", "")
return cmd
}

Expand Down
14 changes: 5 additions & 9 deletions cli/controller/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ type Setup struct {
credentialsProvider int
force bool
yes bool
ghUser string
ghOrg string
githubID string
}

type stackTemplateData struct {
Expand Down Expand Up @@ -72,8 +71,7 @@ func NewSetup(a *SetupArgs) (*Setup, error) {
credentialsProvider: a.credentialsProvider,
force: a.Force,
yes: a.Yes,
ghUser: a.GithubUser,
ghOrg: a.GithubOrg,
githubID: a.GithubID,
}, nil
}

Expand All @@ -85,7 +83,7 @@ Available regions are:
}
ws := c.store.Workspace()
bucket, key := getPath(c.aws.Region())
ghAuth := c.ghOrg != "" || c.ghUser != ""
ghAuth := c.githubID != ""
n, err := ws.NewNode(c.nodeName, c.aws.AccountID(), c.aws.Region(), bucket, key, version, ghAuth)
if err != nil {
return log.Wrap(err)
Expand Down Expand Up @@ -135,8 +133,7 @@ func (c *Setup) create(n *domain.Node) error {
NamingTemplate: n.ResourceNamingTemplate(),
APIGatewayLogsRole: APIGatewayLogsRole,
ResourceTags: c.resourceTags,
GithubUser: c.ghUser,
GithubOrg: c.ghOrg,
GithubID: c.githubID,
}
rsp := &dto.SetupResponse{}
if err := invoke.Lambda(c.aws.Lambda(), c.lambdaName, ui.NodeLogsSink).Do("create", req, rsp); err != nil {
Expand Down Expand Up @@ -231,8 +228,7 @@ func (c *Setup) upgrade(n *domain.Node) error {
ResourceSuffix: n.ResourceSuffix(),
NamingTemplate: n.ResourceNamingTemplate(),
ResourceTags: c.resourceTags,
GithubUser: c.ghUser,
GithubOrg: c.ghOrg,
GithubID: c.githubID,
}
if err := invoke.Lambda(c.aws.Lambda(), c.lambdaName, ui.NodeLogsSink).Do("upgrade", req, nil); err != nil {
return log.Wrap(err, "failed to invoke setup function")
Expand Down
6 changes: 1 addition & 5 deletions cli/controller/setup_args.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ type SetupArgs struct {
credentialsProvider int
Force bool
Yes bool
GithubUser string
GithubOrg string
GithubID string
}

func DefaultNodeName() string { return domain.DefaultNodeName }
Expand All @@ -55,9 +54,6 @@ func (a *SetupArgs) validate() error {
a.credentialsProvider = domain.AWSCredentialsByProfile
return nil
}
if a.GithubOrg != "" && a.GithubUser != "" {
return log.Wrap(NewArgumentError("cannot set both `github-user` and `github-org`"))
}
return log.Wrap(NewArgumentError("AWS credentials not provided"))
}

Expand Down
37 changes: 6 additions & 31 deletions domain/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@ const (
)

type AccessTokenClaims struct {
Workspace string `json:"w,omitempty"`
Project string `json:"p,omitempty"`
Projects []string `json:"j,omitempty"`
Stage string `json:"s,omitempty"`
Runtime string `json:"r,omitempty"`
Username string `json:"u,omitempty"`
Role Role `json:"o,omitempty"`
Workspace string `json:"w,omitempty"`
Project string `json:"p,omitempty"`
Stage string `json:"s,omitempty"`
Runtime string `json:"r,omitempty"`
Username string `json:"u,omitempty"`
Role Role `json:"o,omitempty"`
}

type Role int
Expand Down Expand Up @@ -69,30 +68,6 @@ func IsOwner(ctx context.Context) (bool, error) {
return claims.Role == Owner, nil
}

func IsAuthorizedForProject(ctx context.Context, project string) (bool, error) {
claims, err := ClaimsFromContext(ctx)
if err != nil {
return false, err
}
return isAuthorizedForProject(claims, project), nil
}

func isAuthorizedForProject(claims *AccessTokenClaims, project string) bool {
switch claims.Role {
case Owner:
return true
case Member:
for _, p := range claims.Projects {
if project == p {
return true
}
}
return false
default:
return false
}
}

func ClaimsFromContext(ctx context.Context) (*AccessTokenClaims, error) {
lctx, ok := mantil.FromContext(ctx)
if !ok {
Expand Down
16 changes: 0 additions & 16 deletions domain/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,3 @@ func TestClaimsFromContext(t *testing.T) {
Role: Maintainer,
}, c)
}

func TestIsAuthorizedForProject(t *testing.T) {
c := &AccessTokenClaims{
Role: Owner,
}
require.True(t, isAuthorizedForProject(c, "project"))
c = &AccessTokenClaims{
Role: Member,
}
require.False(t, isAuthorizedForProject(c, "project"))
c = &AccessTokenClaims{
Role: Member,
Projects: []string{"project"},
}
require.True(t, isAuthorizedForProject(c, "project"))
}
7 changes: 3 additions & 4 deletions domain/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ const (
EnvSSMPathPrefix = "MANTIL_SSM_PATH_PREFIX"
EnvKVTable = "MANTIL_KV_TABLE"

SSMPublicKey = "public_key"
SSMPrivateKey = "private_key"
SSMGithubUserKey = "github_user"
SSMGithubOrgKey = "github_org"
SSMPublicKey = "public_key"
SSMPrivateKey = "private_key"
SSMGithubIDKey = "github_id"

TagWorkspace = EnvWorkspace
TagKey = EnvKey
Expand Down
5 changes: 0 additions & 5 deletions node/api/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"

"github.com/mantil-io/mantil/domain"
"github.com/mantil-io/mantil/kit/aws"
"github.com/mantil-io/mantil/node/dto"
"github.com/mantil-io/mantil/node/terraform"
Expand All @@ -21,10 +20,6 @@ func New() *Deploy {
}

func (d *Deploy) Invoke(ctx context.Context, req dto.DeployRequest) (*dto.DeployResponse, error) {
ok, _ := domain.IsAuthorizedForProject(ctx, req.ProjectName)
if !ok {
return nil, domain.ErrNotAuthorized
}
if err := d.init(req); err != nil {
return nil, err
}
Expand Down
5 changes: 0 additions & 5 deletions node/api/destroy/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"

"github.com/mantil-io/mantil/domain"
"github.com/mantil-io/mantil/kit/aws"
"github.com/mantil-io/mantil/node/dto"
"github.com/mantil-io/mantil/node/terraform"
Expand All @@ -20,10 +19,6 @@ func New() *Destroy {
}

func (d *Destroy) Invoke(ctx context.Context, req dto.DestroyRequest) error {
ok, _ := domain.IsAuthorizedForProject(ctx, req.ProjectName)
if !ok {
return domain.ErrNotAuthorized
}
if err := d.init(req); err != nil {
return err
}
Expand Down
Loading

0 comments on commit 047679a

Please sign in to comment.