Introduce service accounts and bootstrap tokens (#22)

This commit is contained in:
Nikolay Edigaryev
2023-02-21 11:34:12 -05:00
committed by GitHub
parent edb9b3d693
commit 8df31f7c2d
37 changed files with 1245 additions and 40 deletions
+134
View File
@@ -0,0 +1,134 @@
package controller
import (
"errors"
storepkg "github.com/cirruslabs/orchard/internal/controller/store"
"github.com/cirruslabs/orchard/internal/responder"
v1 "github.com/cirruslabs/orchard/pkg/resource/v1"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"net/http"
"time"
)
func (controller *Controller) createServiceAccount(ctx *gin.Context) responder.Responder {
if !controller.authorize(ctx, v1.ServiceAccountRoleAdminWrite) {
return responder.Code(http.StatusUnauthorized)
}
var serviceAccount v1.ServiceAccount
if err := ctx.ShouldBindJSON(&serviceAccount); err != nil {
return responder.Code(http.StatusBadRequest)
}
if serviceAccount.Name == "" {
return responder.Code(http.StatusPreconditionFailed)
}
if serviceAccount.Token == "" {
serviceAccount.Token = uuid.New().String()
}
serviceAccount.CreatedAt = time.Now()
serviceAccount.DeletedAt = time.Time{}
serviceAccount.UID = uuid.New().String()
serviceAccount.Generation = 0
return controller.storeUpdate(func(txn storepkg.Transaction) responder.Responder {
// Does the Service Account resource with this name already exists?
_, err := txn.GetServiceAccount(serviceAccount.Name)
if !errors.Is(err, storepkg.ErrNotFound) {
return responder.Code(http.StatusConflict)
}
if err := txn.SetServiceAccount(&serviceAccount); err != nil {
return responder.Code(http.StatusInternalServerError)
}
return responder.JSON(http.StatusOK, &serviceAccount)
})
}
func (controller *Controller) updateServiceAccount(ctx *gin.Context) responder.Responder {
if !controller.authorize(ctx, v1.ServiceAccountRoleAdminWrite) {
return responder.Code(http.StatusUnauthorized)
}
var userServiceAccount v1.ServiceAccount
if err := ctx.ShouldBindJSON(&userServiceAccount); err != nil {
return responder.Code(http.StatusBadRequest)
}
if userServiceAccount.Name == "" {
return responder.Code(http.StatusPreconditionFailed)
}
if userServiceAccount.Token == "" {
return responder.Code(http.StatusPreconditionFailed)
}
return controller.storeUpdate(func(txn storepkg.Transaction) responder.Responder {
dbServiceAccount, err := txn.GetServiceAccount(userServiceAccount.Name)
if err != nil {
return responder.Error(err)
}
dbServiceAccount.Generation++
if err := txn.SetServiceAccount(dbServiceAccount); err != nil {
return responder.Code(http.StatusInternalServerError)
}
return responder.JSON(http.StatusOK, &dbServiceAccount)
})
}
func (controller *Controller) getServiceAccount(ctx *gin.Context) responder.Responder {
if !controller.authorize(ctx, v1.ServiceAccountRoleAdminRead) {
return responder.Code(http.StatusUnauthorized)
}
name := ctx.Param("name")
return controller.storeView(func(txn storepkg.Transaction) responder.Responder {
serviceAccount, err := txn.GetServiceAccount(name)
if err != nil {
return responder.Error(err)
}
return responder.JSON(http.StatusOK, &serviceAccount)
})
}
func (controller *Controller) listServiceAccounts(ctx *gin.Context) responder.Responder {
if !controller.authorize(ctx, v1.ServiceAccountRoleAdminRead) {
return responder.Code(http.StatusUnauthorized)
}
return controller.storeView(func(txn storepkg.Transaction) responder.Responder {
serviceAccounts, err := txn.ListServiceAccounts()
if err != nil {
return responder.Error(err)
}
return responder.JSON(http.StatusOK, &serviceAccounts)
})
}
func (controller *Controller) deleteServiceAccount(ctx *gin.Context) responder.Responder {
if !controller.authorize(ctx, v1.ServiceAccountRoleAdminWrite) {
return responder.Code(http.StatusUnauthorized)
}
name := ctx.Param("name")
return controller.storeUpdate(func(txn storepkg.Transaction) responder.Responder {
if err := txn.DeleteServiceAccount(name); err != nil {
return responder.Error(err)
}
return responder.Code(http.StatusOK)
})
}