Skip to content

Commit

Permalink
Updated CRUD operations for task secrets.
Browse files Browse the repository at this point in the history
  • Loading branch information
Vladimir Kupriyanov committed Feb 21, 2024
1 parent f8477bc commit dd57c25
Show file tree
Hide file tree
Showing 8 changed files with 325 additions and 50 deletions.
38 changes: 38 additions & 0 deletions controllers/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ func (jc *JobController) SetJobRoutes(rg *gin.RouterGroup, config config.Config)
r.GET("", middlewares.SetAuthorizationListMiddleware(jc.AuthService, "jobs"), jc.ListJobs)
r.GET("/:id", middlewares.AuthorizationMiddleware(jc.AuthService, "jobs", "read"), jc.GetJob)
r.GET("/:id/log", middlewares.AuthorizationMiddleware(jc.AuthService, "jobs", "read"), jc.GetJobLog)
r.GET("/:id/", middlewares.AuthorizationMiddleware(jc.AuthService, "jobs", "read"), jc.GetJobLog)
r.GET("/:id/schema", middlewares.AuthorizationMiddleware(jc.AuthService, "jobs", "read"), jc.GetSchema)

r.Use(middlewares.AuthorizationMiddleware(jc.AuthService, "jobs", "write"))
{
Expand Down Expand Up @@ -194,3 +196,39 @@ func (jc *JobController) CreateJob(ctx *gin.Context) {
jc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusOK, gin.H{"msg": "job created successfully", "id": job.ID})
}

// GetSchema godoc
//
// @Summary Get task schema
// @Description Get task schema for the job info and input parameters
// @Tags jobs
// @Accept json
// @Produce json
// @Param id path string true "Task name"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} helpers.HTTPError
// @Failure 404 {object} helpers.HTTPError
// @Failure 500 {object} helpers.HTTPError
// @Router /jobs/{id} [get]
// @Security Bearer
func (jc *JobController) GetSchema(ctx *gin.Context) {
taskName := ctx.Param("id")
audit := jc.AuditService.InitialiseAuditLog(ctx, "get_schema", jc.AuditCategory, taskName)
schema, err := jc.JobService.GetSchema(taskName)

if err != nil {
jc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
audit.Status = "success"

if schema == nil {
jc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusOK, gin.H{"msg": "schema not found"})
return
}

jc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusOK, schema)
}
122 changes: 117 additions & 5 deletions controllers/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ func (tc *TaskController) SetTaskRoutes(rg *gin.RouterGroup, config config.Confi
r.POST("/:id/schema", tc.UpdateSchema)
r.PUT("/:id/schema", tc.UpdateSchema)
r.DELETE("/:id/schema", tc.DeleteSchema)

r.GET("/:id/secret", tc.GetSecret)
r.POST("/:id/secret", tc.UpdateSecret)
r.PUT("/:id/secret", tc.UpdateSecret)
r.DELETE("/:id/secret", tc.DeleteSecret)
}
}

Expand Down Expand Up @@ -112,7 +117,7 @@ func (tc *TaskController) GetTask(ctx *gin.Context) {
taskName := ctx.Param("id")
audit := tc.AuditService.InitialiseAuditLog(ctx, "get", tc.AuditCategory, taskName)
// username := ctx.MustGet("username").(string)
task, _, err := tc.TaskService.GetTask(taskName)
task, secret, err := tc.TaskService.GetTask(taskName)

if err != nil {
tc.AuditService.CreateAudit(audit)
Expand All @@ -127,6 +132,7 @@ func (tc *TaskController) GetTask(ctx *gin.Context) {
}
audit.Status = "success"

task["secret"] = secret
// ctx.JSON(http.StatusOK, gin.H{"msg": "task retrieved successfully", "value": task, "secret": secret})
tc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusOK, task)
Expand Down Expand Up @@ -157,7 +163,7 @@ func (tc *TaskController) CreateTask(ctx *gin.Context) {
}
audit.EventTarget = task.Name

configMap, _, err := tc.TaskService.CreateTask(task)
taskConfig, secret, err := tc.TaskService.CreateTask(task)
if err != nil {
if errors.IsAlreadyExists(err) {
tc.AuditService.CreateAudit(audit)
Expand All @@ -170,8 +176,9 @@ func (tc *TaskController) CreateTask(ctx *gin.Context) {
}

audit.Status = "success"
taskConfig["secret"] = secret
tc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusOK, configMap.Data)
ctx.JSON(http.StatusOK, taskConfig)
}

// UpdateTask godoc
Expand Down Expand Up @@ -200,7 +207,7 @@ func (tc *TaskController) UpdateTask(ctx *gin.Context) {
return
}

configMap, _, err := tc.TaskService.UpdateTask(task)
taskConfig, secret, err := tc.TaskService.UpdateTask(task)
if err != nil {
if errors.IsNotFound(err) {
tc.AuditService.CreateAudit(audit)
Expand All @@ -213,7 +220,8 @@ func (tc *TaskController) UpdateTask(ctx *gin.Context) {
}
audit.Status = "success"
tc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusOK, configMap.Data)
taskConfig["secret"] = secret
ctx.JSON(http.StatusOK, taskConfig)
}

// DeleteTask godoc
Expand Down Expand Up @@ -354,3 +362,107 @@ func (tc *TaskController) DeleteSchema(ctx *gin.Context) {
tc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusOK, gin.H{"msg": "schema deleted successfully"})
}

// GetSecret godoc
//
// @Summary Get secret
// @Description Get secret associated to a specific task (passwords are obfuscated)
// @Tags tasks
// @Accept json
// @Produce json
// @Param id path string true "Task name"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} helpers.HTTPError
// @Failure 404 {object} helpers.HTTPError
// @Failure 500 {object} helpers.HTTPError
// @Router /tasks/{id}/secret [get]
// @Security Bearer
func (tc *TaskController) GetSecret(ctx *gin.Context) {
taskName := ctx.Param("id")
audit := tc.AuditService.InitialiseAuditLog(ctx, "get_secret", tc.AuditCategory, taskName)
secret, err := tc.TaskService.GetSecret(taskName)

if err != nil {
tc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

if secret == nil {
ctx.JSON(http.StatusOK, gin.H{"msg": "secret not found"})
return
}

audit.Status = "success"
tc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusOK, secret)
}

// GetSecret godoc
//
// @Summary Update secret
// @Description Update secret associated to a specific task
// @Tags tasks
// @Accept json
// @Produce json
// @Param id path string true "Task name"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} helpers.HTTPError
// @Failure 404 {object} helpers.HTTPError
// @Failure 500 {object} helpers.HTTPError
// @Router /tasks/{id}/secret [get]
// @Security Bearer
func (tc *TaskController) UpdateSecret(ctx *gin.Context) {
taskName := ctx.Param("id")
audit := tc.AuditService.InitialiseAuditLog(ctx, "update_secret", tc.AuditCategory, taskName)
var secret map[string]string

if err := ctx.BindJSON(&secret); err != nil {
tc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

secretStored, err := tc.TaskService.UpdateSecret(taskName, secret)

if err != nil {
tc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

audit.Status = "success"
tc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusOK, secretStored)
}

// DeleteSecret godoc
//
// @Summary Delete secret
// @Description Remove secret associated to a specific task
// @Tags tasks
// @Accept json
// @Produce json
// @Param id path string true "Task name"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} helpers.HTTPError
// @Failure 404 {object} helpers.HTTPError
// @Failure 500 {object} helpers.HTTPError
// @Router /tasks/{id}/schema [delete]
// @Security Bearer
func (tc *TaskController) DeleteSecret(ctx *gin.Context) {
taskName := ctx.Param("id")
audit := tc.AuditService.InitialiseAuditLog(ctx, "delete_secret", tc.AuditCategory, taskName)

err := tc.TaskService.DeleteSecret(taskName)

if err != nil {
tc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

audit.Status = "success"
tc.AuditService.CreateAudit(audit)
ctx.JSON(http.StatusOK, gin.H{"msg": "secret deleted successfully"})
}
3 changes: 2 additions & 1 deletion middlewares/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func AuthorizationMiddleware(as services.AuthService, resource string, access st
return func(ctx *gin.Context) {
userID := ctx.MustGet("userID").(uuid.UUID)
provider := ctx.MustGet("provider").(string)
requestUrl := ctx.Request.URL.String()

resourceID := ctx.Param("id")
if resourceID == "" {
Expand All @@ -54,7 +55,7 @@ func AuthorizationMiddleware(as services.AuthService, resource string, access st

// trimming last 6 chars for jobs read because
// jobs include random caracters at the end
if resource == "jobs" && access == "read" {
if resource == "jobs" && access == "read" && !strings.HasSuffix(requestUrl, "/schema") {
resourceID = resourceID[:len(resourceID)-6]
}

Expand Down
6 changes: 2 additions & 4 deletions services/audit_svc.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ func NewAuditService(database *gorm.DB, config config.Config) AuditService {

func (a *AuditServiceImpl) ListAuditLogs(max int) ([]models.AuditLog, error) {
var logs []models.AuditLog
var res *gorm.DB

res = a.db.Order("created_at desc").Limit(max).Find(&logs)
res := a.db.Order("created_at desc").Limit(max).Find(&logs)
if res.Error != nil {
return logs, res.Error
}
Expand All @@ -49,7 +47,7 @@ func (a *AuditServiceImpl) GetAuditLog(id string) (models.AuditLog, error) {
}

if log.UserName == "" {
return models.AuditLog{}, fmt.Errorf("Audit log %s not found, please check uuid", id)
return models.AuditLog{}, fmt.Errorf("audit log %s not found, please check uuid", id)
}

return log, nil
Expand Down
2 changes: 1 addition & 1 deletion services/auth_svc.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,12 @@ func (a *AuthServiceImpl) GetRootPassword() (string, error) {
}

func (a *AuthServiceImpl) IsAutorised(auth *models.Authorization) (bool, error) {

roles, err := a.UserService.GetUserRoles(auth.UserID.String(), auth.Provider)
if err != nil {
log.Println(err)
return false, err
}

for _, role := range roles {
if role.Resource == "*" || role.Resource == auth.Resource &&
(len(role.Resources_IDs) > 0 && role.Resources_IDs[0] == "*" || slices.Contains(role.Resources_IDs, auth.ResourceID)) &&
Expand Down
23 changes: 23 additions & 0 deletions services/job_svc.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type JobService interface {
GetJob(string, string) (models.Job, error)
CreateJob(string, string, string) (models.Job, error)
GetTaskConfigMap(string) (map[string]string, error)
GetSchema(string) (map[string]interface{}, error)
}

type JobServiceImpl struct {
Expand Down Expand Up @@ -261,3 +262,25 @@ func (j *JobServiceImpl) GetTaskConfigMap(name string) (map[string]string, error

return configMap.Data, err
}

func (j *JobServiceImpl) GetSchema(name string) (map[string]interface{}, error) {
var data map[string]interface{}

configMap, err := helpers.GetConfigMap(j.config.Kube, name)
if err != nil {
return nil, err
}
if configMap.Data["runner"] == "" {
return nil, fmt.Errorf("task %s not found", name)
}

if configMap.Data["schema"] != "" {
err = json.Unmarshal([]byte(configMap.Data["schema"]), &data)
if err != nil {
return nil, err
}

}

return data, nil
}
Loading

0 comments on commit dd57c25

Please sign in to comment.