feat: Closes #236, Added 3 optional fields in iam user account, UserID, GroupID, ProjectID

This commit is contained in:
jonaustin09
2023-10-12 13:24:34 -04:00
parent 1117879031
commit 920b4945cd
5 changed files with 75 additions and 20 deletions

View File

@@ -21,9 +21,12 @@ import (
// Account is a gateway IAM account
type Account struct {
Access string `json:"access"`
Secret string `json:"secret"`
Role string `json:"role"`
Access string `json:"access"`
Secret string `json:"secret"`
Role string `json:"role"`
UserID int `json:"userID"`
GroupID int `json:"groupID"`
ProjectID int `json:"projectID"`
}
// IAMService is the interface for all IAM service implementations

View File

@@ -135,9 +135,12 @@ func (s *IAMServiceInternal) ListUserAccounts() ([]Account, error) {
var accs []Account
for _, k := range keys {
accs = append(accs, Account{
Access: k,
Secret: conf.AccessAccounts[k].Secret,
Role: conf.AccessAccounts[k].Role,
Access: k,
Secret: conf.AccessAccounts[k].Secret,
Role: conf.AccessAccounts[k].Role,
UserID: conf.AccessAccounts[k].UserID,
GroupID: conf.AccessAccounts[k].GroupID,
ProjectID: conf.AccessAccounts[k].ProjectID,
})
}

View File

@@ -15,6 +15,7 @@
package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
@@ -67,6 +68,21 @@ func adminCommand() *cli.Command {
Required: true,
Aliases: []string{"r"},
},
&cli.IntFlag{
Name: "user-id",
Usage: "userID for the new user",
Aliases: []string{"ui"},
},
&cli.IntFlag{
Name: "group-id",
Usage: "groupID for the new user",
Aliases: []string{"gi"},
},
&cli.IntFlag{
Name: "project-id",
Usage: "projectID for the new user",
Aliases: []string{"pi"},
},
},
},
{
@@ -144,6 +160,7 @@ func adminCommand() *cli.Command {
func createUser(ctx *cli.Context) error {
access, secret, role := ctx.String("access"), ctx.String("secret"), ctx.String("role")
userID, groupID, projectID := ctx.Int("user-id"), ctx.Int("group-id"), ctx.Int("projectID")
if access == "" || secret == "" {
return fmt.Errorf("invalid input parameters for the new user")
}
@@ -151,14 +168,28 @@ func createUser(ctx *cli.Context) error {
return fmt.Errorf("invalid input parameter for role")
}
req, err := http.NewRequest(http.MethodPatch, fmt.Sprintf("%v/create-user?access=%v&secret=%v&role=%v", adminEndpoint, access, secret, role), nil)
acc := auth.Account{
Access: access,
Secret: secret,
Role: role,
UserID: userID,
GroupID: groupID,
ProjectID: projectID,
}
accJson, err := json.Marshal(acc)
if err != nil {
return fmt.Errorf("failed to parse user data: %w", err)
}
req, err := http.NewRequest(http.MethodPatch, fmt.Sprintf("%v/create-user", adminEndpoint), bytes.NewBuffer(accJson))
if err != nil {
return fmt.Errorf("failed to send the request: %w", err)
}
signer := v4.NewSigner()
hashedPayload := sha256.Sum256([]byte{})
hashedPayload := sha256.Sum256(accJson)
hexPayload := hex.EncodeToString(hashedPayload[:])
req.Header.Set("X-Amz-Content-Sha256", hexPayload)
@@ -262,6 +293,7 @@ func listUsers(ctx *cli.Context) error {
if err := json.Unmarshal(body, &accs); err != nil {
return err
}
fmt.Println(accs)
printAcctTable(accs)
@@ -280,10 +312,10 @@ const (
func printAcctTable(accs []auth.Account) {
w := new(tabwriter.Writer)
w.Init(os.Stdout, minwidth, tabwidth, padding, padchar, flags)
fmt.Fprintln(w, "Account\tRole")
fmt.Fprintln(w, "-------\t----")
fmt.Fprintln(w, "Account\tRole\tUserID\tGroupID\tProjectID")
fmt.Fprintln(w, "-------\t----\t------\t-------\t---------")
for _, acc := range accs {
fmt.Fprintf(w, "%v\t%v\n", acc.Access, acc.Role)
fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\n", acc.Access, acc.Role, acc.UserID, acc.GroupID, acc.ProjectID)
}
fmt.Fprintln(w)
w.Flush()

View File

@@ -15,6 +15,7 @@
package controllers
import (
"encoding/json"
"fmt"
"github.com/gofiber/fiber/v2"
@@ -32,19 +33,21 @@ func NewAdminController(iam auth.IAMService, be backend.Backend) AdminController
}
func (c AdminController) CreateUser(ctx *fiber.Ctx) error {
access, secret, role := ctx.Query("access"), ctx.Query("secret"), ctx.Query("role")
acct := ctx.Locals("account").(auth.Account)
if acct.Role != "admin" {
return fmt.Errorf("access denied: only admin users have access to this resource")
}
if role != "user" && role != "admin" {
var usr auth.Account
err := json.Unmarshal(ctx.Body(), &usr)
if err != nil {
return fmt.Errorf("failed to parse request body: %w", err)
}
if usr.Role != "user" && usr.Role != "admin" {
return fmt.Errorf("invalid parameters: user role have to be one of the following: 'user', 'admin'")
}
user := auth.Account{Access: access, Secret: secret, Role: role}
err := c.iam.CreateAccount(user)
err = c.iam.CreateAccount(usr)
if err != nil {
return fmt.Errorf("failed to create a user: %w", err)
}

View File

@@ -15,7 +15,9 @@
package controllers
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
@@ -55,6 +57,18 @@ func TestAdminController_CreateUser(t *testing.T) {
return ctx.Next()
})
usr := auth.Account{
Access: "access",
Secret: "secret",
Role: "invalid role",
}
user, _ := json.Marshal(&usr)
usr.Role = "admin"
succUsr, _ := json.Marshal(&usr)
appErr.Patch("/create-user", adminController.CreateUser)
tests := []struct {
@@ -68,7 +82,7 @@ func TestAdminController_CreateUser(t *testing.T) {
name: "Admin-create-user-success",
app: app,
args: args{
req: httptest.NewRequest(http.MethodPatch, "/create-user?access=test&secret=test&role=user", nil),
req: httptest.NewRequest(http.MethodPatch, "/create-user", bytes.NewBuffer(succUsr)),
},
wantErr: false,
statusCode: 200,
@@ -77,7 +91,7 @@ func TestAdminController_CreateUser(t *testing.T) {
name: "Admin-create-user-invalid-user-role",
app: app,
args: args{
req: httptest.NewRequest(http.MethodPatch, "/create-user?access=test&secret=test&role=invalid", nil),
req: httptest.NewRequest(http.MethodPatch, "/create-user", bytes.NewBuffer(user)),
},
wantErr: false,
statusCode: 500,
@@ -86,7 +100,7 @@ func TestAdminController_CreateUser(t *testing.T) {
name: "Admin-create-user-invalid-requester-role",
app: appErr,
args: args{
req: httptest.NewRequest(http.MethodPatch, "/create-user?access=test&secret=test&role=admin", nil),
req: httptest.NewRequest(http.MethodPatch, "/create-user", nil),
},
wantErr: false,
statusCode: 500,