app/registry/trembita_client.go (224 lines of code) (raw):

package registry import ( "ddm-admin-console/router" "encoding/json" "fmt" "net/http" "reflect" "strings" "time" "github.com/gin-gonic/gin" "github.com/pkg/errors" ) const ( MRLabelTargetTrembitaRegistryUpdate = "trembita-registry-update" MRLabelTrembitaRegsitryName = "trembita-registry-name" ) type TrembitaClientRegistryForm struct { TrembitaClientProtocolVersion string `form:"trembita-client-protocol-version" binding:"required"` TrembitaClientURL string `form:"trembita-client-url"` TrembitaClientUserID string `form:"trembita-client-user-id" binding:"required"` TrembitaClientXRoadInstance string `form:"trembita-client-x-road-instance" binding:"required"` TrembitaClientMemberClass string `form:"trembita-client-member-class" binding:"required"` TrembitaClientMemberCode string `form:"trembita-client-member-code" binding:"required"` TrembitaClientSubsystemCode string `form:"trembita-client-subsystem-code" binding:"required"` TrembitaClientRegitryName string `form:"trembita-client-regitry-name" binding:"required"` TrembitaClientProtocol string `form:"trembita-client-protocol" binding:"required"` TrembitaServiceXRoadInstance string `form:"trembita-service-x-road-instance" binding:"required"` TrembitaServiceMemberClass string `form:"trembita-service-member-class" binding:"required"` TrembitaServiceMemberCode string `form:"trembita-service-member-code" binding:"required"` TrembitaServiceSubsystemCode string `form:"trembita-service-subsystem-code" binding:"required"` TrembitaServiceServiceCode string `form:"trembita-service-service-code"` TrembitaServiceServiceVersion string `form:"trembita-service-service-version"` TrembitaServiceAuthType string `form:"trembita-service-auth-type" binding:"required"` TrembitaServiceAuthSecret string `form:"trembita-service-auth-secret"` } func (tf TrembitaClientRegistryForm) ToNestedStruct(wiremockAddr string) TrembitaRegistry { tr := TrembitaRegistry{ URL: tf.TrembitaClientURL, UserID: tf.TrembitaClientUserID, ProtocolVersion: tf.TrembitaClientProtocolVersion, Client: TrembitaRegistryClient{ MemberClass: tf.TrembitaClientMemberClass, MemberCode: tf.TrembitaClientMemberCode, SubsystemCode: tf.TrembitaClientSubsystemCode, XRoadInstance: tf.TrembitaClientXRoadInstance, }, Service: TrembitaRegistryService{ MemberCode: tf.TrembitaServiceMemberCode, MemberClass: tf.TrembitaServiceMemberClass, XRoadInstance: tf.TrembitaServiceXRoadInstance, SubsystemCode: tf.TrembitaServiceSubsystemCode, ServiceCode: tf.TrembitaServiceServiceCode, ServiceVersion: tf.TrembitaServiceServiceVersion, }, Auth: map[string]string{ "type": tf.TrembitaServiceAuthType, }, } if tr.URL == "" { tr.Mock = true tr.URL = wiremockAddr } return tr } func (a *App) setTrembitaClientRegistryData(ctx *gin.Context) (rsp router.Response, retErr error) { registryName := ctx.Param("name") _, err := a.Codebase.Get(registryName) if err != nil { return nil, errors.Wrap(err, "unable to find registry") } var tf TrembitaClientRegistryForm if err := ctx.ShouldBind(&tf); err != nil { return nil, errors.Wrap(err, "unable to parse form") } values, err := GetValuesFromGit(registryName, MasterBranch, a.Gerrit) if err != nil { return nil, errors.Wrap(err, "unable to get values") } trembitaRegistryFromValues, ok := values.Trembita.Registries[tf.TrembitaClientRegitryName] if !ok { return nil, errors.New("wrong registry name") } trembitaRegistry := tf.ToNestedStruct(strings.ReplaceAll(a.Config.WiremockAddr, registryNamePlaceholder, registryName)) trembitaRegistry.Type = trembitaRegistryFromValues.Type trembitaRegistry.Protocol = trembitaRegistryFromValues.Protocol trembita, ok := values.OriginalYaml[trembitaValuesKey] if !ok { return nil, errors.New("no trembita config in values") } trembitaDict := trembita.(map[string]interface{}) registriesDict := trembitaDict[trembitaRegistriesValuesKet].(map[string]interface{}) //TODO: change path to single secret vault:secret/<registry>/trembita-registries //TODO: check if keys rewrited or keep if tf.TrembitaServiceAuthType == authTypeAuthToken && tf.TrembitaServiceAuthSecret != "" { vaultPath := fmt.Sprintf("%s/trembita-registries/%s-%s", a.vaultRegistryPath(registryName), tf.TrembitaClientRegitryName, time.Now().Format("20060201T150405Z")) prefixedPath := fmt.Sprintf("vault:%s", vaultPath) if tf.TrembitaServiceAuthSecret != prefixedPath { if err := CreateVaultSecrets(a.Vault, map[string]map[string]interface{}{ vaultPath: { fmt.Sprintf("trembita.registries.%s.auth.secret.token", tf.TrembitaClientRegitryName): tf.TrembitaServiceAuthSecret, }, }, true); err != nil { return nil, errors.Wrap(err, "unable to create auth token secret") } } //todo: maybe move to nested struct converter trembitaRegistry.Auth["secret"] = prefixedPath } registriesDict[tf.TrembitaClientRegitryName] = trembitaRegistry trembitaDict[trembitaRegistriesKey] = registriesDict values.OriginalYaml[trembitaValuesKey] = trembitaDict if err := CreateEditMergeRequest(ctx, registryName, values.OriginalYaml, a.Gerrit, []string{}, MRLabel{Key: MRLabelTarget, Value: MRLabelTargetTrembitaRegistryUpdate}, MRLabel{Key: MRLabelTrembitaRegsitryName, Value: tf.TrembitaClientRegitryName}); err != nil { return nil, errors.Wrap(err, "unable to create merge request") } return router.MakeRedirectResponse(http.StatusFound, fmt.Sprintf("/admin/registry/view/%s", registryName)), nil } func (a *App) createTrembitaClientRegistry(ctx *gin.Context) (rsp router.Response, retErr error) { registryName := ctx.Param("name") _, err := a.Codebase.Get(registryName) if err != nil { return nil, errors.Wrap(err, "unable to find registry") } var tf TrembitaClientRegistryForm if err := ctx.ShouldBind(&tf); err != nil { return nil, errors.Wrap(err, "unable to parse form") } values, err := GetValuesFromGit(registryName, MasterBranch, a.Gerrit) if err != nil { return nil, errors.Wrap(err, "unable to get values") } _, ok := values.Trembita.Registries[tf.TrembitaClientRegitryName] if ok { return nil, errors.Wrap(err, "trembita client already exists") } trembitaRegistry := tf.ToNestedStruct(strings.ReplaceAll(a.Config.WiremockAddr, registryNamePlaceholder, registryName)) trembitaRegistry.Type = externalSystemDeletableType trembitaRegistry.Protocol = tf.TrembitaClientProtocol if tf.TrembitaServiceAuthType == authTypeAuthToken && tf.TrembitaServiceAuthSecret != "" { vaultPath := fmt.Sprintf("%s/trembita-registries/%s-%s", a.vaultRegistryPath(registryName), tf.TrembitaClientRegitryName, time.Now().Format("20060201T150405Z")) prefixedPath := fmt.Sprintf("vault:%s", vaultPath) if tf.TrembitaServiceAuthSecret != prefixedPath { if err := CreateVaultSecrets(a.Vault, map[string]map[string]interface{}{ vaultPath: { fmt.Sprintf("trembita.registries.%s.auth.secret.token", tf.TrembitaClientRegitryName): tf.TrembitaServiceAuthSecret, }, }, true); err != nil { return nil, errors.Wrap(err, "unable to create auth token secret") } } trembitaRegistry.Auth["secret"] = prefixedPath } values.Trembita.Registries[tf.TrembitaClientRegitryName] = trembitaRegistry values.OriginalYaml[trembitaValuesKey] = values.Trembita if err := CreateEditMergeRequest(ctx, registryName, values.OriginalYaml, a.Gerrit, []string{}, MRLabel{Key: MRLabelTarget, Value: MRLabelTargetTrembitaRegistryUpdate}, MRLabel{Key: MRLabelTrembitaRegsitryName, Value: tf.TrembitaClientRegitryName}); err != nil { return nil, errors.Wrap(err, "unable to create merge request") } return router.MakeRedirectResponse(http.StatusFound, fmt.Sprintf("/admin/registry/view/%s", registryName)), nil } func (a *App) deleteTrembitaClient(ctx *gin.Context) (rsp router.Response, retErr error) { registryName := ctx.Param("name") _, err := a.Codebase.Get(registryName) if err != nil { return nil, errors.Wrap(err, "unable to find registry") } trembitaClientName := ctx.Query("trembita-client") values, err := GetValuesFromGit(registryName, MasterBranch, a.Gerrit) if err != nil { return nil, errors.Wrap(err, "unable to get values") } trembita, ok := values.Trembita.Registries[trembitaClientName] if !ok { return nil, errors.New("trembita client does not exists") } if trembita.Type == "platform" { return nil, errors.New("trembita client is unavailable to delete") } delete(values.Trembita.Registries, trembitaClientName) values.OriginalYaml[trembitaValuesKey] = values.Trembita if err := CreateEditMergeRequest(ctx, registryName, values.OriginalYaml, a.Gerrit, []string{}); err != nil { return nil, errors.Wrap(err, "unable to create merge request") } return router.MakeRedirectResponse(http.StatusFound, fmt.Sprintf("/admin/registry/view/%s", registryName)), nil } func (a *App) checkTrembitaClientExists(ctx *gin.Context) (rsp router.Response, retErr error) { registryName := ctx.Param("name") _, err := a.Codebase.Get(registryName) if err != nil { return nil, errors.Wrap(err, "unable to find registry") } trembitaClientName := ctx.Query("trembita-client") values, err := GetValuesFromGit(registryName, MasterBranch, a.Gerrit) if err != nil { return nil, errors.Wrap(err, "unable to get values") } _, ok := values.Trembita.Registries[trembitaClientName] if ok { return router.MakeStatusResponse(http.StatusOK), nil } return router.MakeStatusResponse(http.StatusNotFound), nil } func (a *App) prepareTrembitaIPList(ctx *gin.Context, r *registry, values *Values, secrets map[string]map[string]interface{}, mrActions *[]string) (bool, error) { valuesChanged := false if r.TrembitaIPList != "" { var ipList []string if err := json.Unmarshal([]byte(r.TrembitaIPList), &ipList); err != nil { return false, fmt.Errorf("unable to decode trembita ip list %w", err) } valuesChanged = !reflect.DeepEqual(values.Trembita.IPList, ipList) values.Trembita.IPList = ipList values.OriginalYaml[trembitaValuesKey] = values.Trembita } else if r.TrembitaIPList == "" && len(values.Trembita.IPList) > 0 { values.Trembita.IPList = []string{} values.OriginalYaml[trembitaValuesKey] = values.Trembita valuesChanged = true } return valuesChanged, nil }