package controllers import ( "encoding/json" "oc-datacenter/infrastructure" oclib "cloud.o-forge.io/core/oc-lib" "cloud.o-forge.io/core/oc-lib/models/live" beego "github.com/beego/beego/v2/server/web" ) type MinioController struct { beego.Controller } // @Title CreateServiceAccounnt // @Description Add a new ServiceAccount to a Minio server using its ID and an execution ID and store the secret holding the login in the appropriate namespace // @Success 201 // @Param executions path string true "The executionsID of the execution" // @Param minioId path string true "The ID of the Minio you want to reach" // @Param retrieve body map[string]string false "Should be empty or contain "'retrieve': true" // @router /serviceaccount/:minioId/:executions [post] func (m *MinioController) CreateServiceAccount() { _, peerID, _ := oclib.ExtractTokenInfo(*m.Ctx.Request) // This part is solely for dev purposes and should be removed once test on executionsId := m.Ctx.Input.Param(":executions") minioId := m.Ctx.Input.Param(":minioId") var b map[string]interface{} retrieve := false json.Unmarshal(m.Ctx.Input.CopyBody(10000), &b) if r, ok := b["retrieve"]; ok { retrieve = r.(bool) } // retrieve the live storage with the minioId access, secret, ok := m.createServiceAccount(minioId, peerID, executionsId) if !ok { return } if retrieve { m.Ctx.Output.SetStatus(201) m.Data["json"] = map[string]string{"access": access, "secret": secret} m.ServeJSON() return } // test if the namespace exists k, err := infrastructure.NewService() if err != nil { m.Ctx.Output.SetStatus(500) m.Data["json"] = map[string]string{"error": err.Error()} m.ServeJSON() return } ns, err := k.GetNamespace(m.Ctx.Request.Context(), executionsId) if ns == nil { m.Ctx.Output.SetStatus(403) m.Data["json"] = map[string]string{"error":"Could not find the namespace corresponding to executionsID " + executionsId} m.ServeJSON() return } if err != nil { m.Ctx.Output.SetStatus(500) m.Data["json"] = map[string]string{"error": "Error when trying to check if namespace " + executionsId + " exists : " + err.Error()} m.ServeJSON() return } // store the credentials in the namespace err = k.CreateSecret(m.Ctx.Request.Context(), minioId, executionsId, access, secret) if err != nil { m.Ctx.Output.SetStatus(500) m.Data["json"] = map[string]string{"error": "Error when storing Minio serviceAccount credentials in namespace " + executionsId + " exists : " + err.Error()} m.ServeJSON() return } m.Data["json"] = map[string]string{"success": "created secret " + executionsId + "-secret-sa in namespace ns-" + executionsId} m.ServeJSON() } func (m *MinioController) createServiceAccount(minioId string, peerID string, executionsId string) (string, string, bool) { s := oclib.NewRequest(oclib.LibDataEnum(oclib.STORAGE_RESOURCE), "", "", []string{}, nil).LoadOne(minioId) if s.Err != "" { m.Ctx.Output.SetStatus(400) m.Data["json"] = map[string]interface{}{"error": " Could not load the storage resource with id " + minioId + ": " + s.Err} m.ServeJSON() return "","", false } live := findLiveStorage(minioId, peerID) if live == nil { m.Ctx.Output.SetStatus(404) m.Data["json"] = map[string]interface{}{"error": "could not find the Minio instance for " + minioId} m.ServeJSON() return "", "", false } url := live.Source service := infrastructure.NewMinioService(url) // call the method ctrating the svcacc err := service.CreateClient() if err != nil { m.Ctx.Output.SetStatus(500) m.Data["json"] = map[string]interface{}{"error": "could not create the client for " + minioId + " : " + err.Error()} m.ServeJSON() return "", "", false } access, secret, err := service.CreateCredentials(executionsId) if err != nil { m.Ctx.Output.SetStatus(500) m.Data["json"] = map[string]interface{}{"error": "could not create the service account for " + minioId + " : " + err.Error()} m.ServeJSON() return "", "", false } err = service.CreateBucket(executionsId) if err != nil { m.Ctx.Output.SetStatus(500) m.Data["json"] = map[string]interface{}{"error": "error while creating the service account for " + minioId + " : " + err.Error()} m.ServeJSON() return "", "", false } return access, secret, true } func findLiveStorage(storageId string, peerId string) *live.LiveStorage { res := oclib.NewRequest(oclib.LibDataEnum(oclib.LIVE_STORAGE),"",peerId,[]string{},nil).LoadAll(false) if res.Err != "" { l := oclib.GetLogger() l.Error().Msg(res.Err) return nil } for _, dbo := range res.Data { r := oclib.NewRequest(oclib.LibDataEnum(oclib.LIVE_STORAGE),"","",[]string{},nil).LoadOne(dbo.GetID()) l := r.ToLiveStorage() for _, id := range l.ResourcesID { if id == storageId { return l } } } return nil } // @Title CreateCredentialsSecret // @Description Create a Kubernetes secret holding the access and secret keys to a given S3 server and bucket // @Success 201 // @Param executions path string true "The executionsID of the execution" // @Param minioId path string true "The ID of the Minio youto which the credentials give access to" // @Param creds body map[string]string true "The credentials to store in the secret" // @router /secret/:minioId/:executions [post] func (m *MinioController) CreateCredentialHoldingSecret(){ executionsId := m.Ctx.Input.Param(":executions") minioId := m.Ctx.Input.Param(":minioId") var creds map[string]string json.Unmarshal(m.Ctx.Input.CopyBody(10000), &creds) access, aOk := creds["access"] secret, sOk := creds["secret"] if !aOk || !sOk || len(access) == 0 || len(secret) == 0 { m.Ctx.Output.SetStatus(403) m.Data["json"] = map[string]interface{}{"error": "Missing credentials"} m.ServeJSON() } // test if the namespace exists k, err := infrastructure.NewService() if err != nil { m.Ctx.Output.SetStatus(500) m.Data["json"] = map[string]string{"error": err.Error()} m.ServeJSON() return } ns, err := k.GetNamespace(m.Ctx.Request.Context(), executionsId) if ns == nil { m.Ctx.Output.SetStatus(403) m.Data["json"] = map[string]string{"error":"Could not find the namespace corresponding to executionsID " + executionsId} m.ServeJSON() return } if err != nil { m.Ctx.Output.SetStatus(500) m.Data["json"] = map[string]string{"error": "Error when trying to check if namespace " + executionsId + " exists : " + err.Error()} m.ServeJSON() return } // store the credentials in the namespace err = k.CreateSecret(m.Ctx.Request.Context(), minioId, executionsId, creds["access"], creds["secret"]) if err != nil { m.Ctx.Output.SetStatus(500) m.Data["json"] = map[string]string{"error": "Error when storing Minio serviceAccount credentials in namespace " + executionsId + " exists : " + err.Error()} m.ServeJSON() return } m.Ctx.Output.SetStatus(201) m.ServeJSON() }