cmd/hub/api/secret.go (228 lines of code) (raw):

// Copyright (c) 2022 EPAM Systems, Inc. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. //go:build api package api import ( "encoding/json" "errors" "fmt" "log" "net/url" "os" "github.com/epam/hubctl/cmd/hub/config" "github.com/epam/hubctl/cmd/hub/util" ) type CreateSecretResponse struct { Id string } func CreateSecret(entityKind, selector, name, component, kind string, values map[string]string) { id := "" resource := "" var parameters []Parameter var qErr error switch entityKind { case "environment": env, err := environmentBy(selector) qErr = err if err == nil && env != nil { id = env.Id resource = environmentsResource parameters = env.Parameters } case "template": template, err := templateBy(selector) qErr = err if err == nil && template != nil { id = template.Id resource = templatesResource parameters = template.Parameters } case "instance": instance, err := stackInstanceBy(selector) qErr = err if err == nil && instance != nil { id = instance.Id resource = stackInstancesResource parameters = instance.Parameters } default: log.Fatalf("Unknown entity kind `%s`", entityKind) } if id == "" && qErr == nil { qErr = errors.New("Not Found") } if qErr != nil { log.Fatalf("Unable to query %s: %v", entityKind, qErr) } for _, existing := range parameters { if !util.Empty(existing.Value) && existing.Name == name && ((existing.Component == "" && component == "") || existing.Component == component) { qname := name if component != "" { qname = fmt.Sprintf("%s|%s", name, component) } log.Fatalf("Parameter `%s` already exist in %s `%s` and is not empty", qname, entityKind, selector) } } secretId, err := createSecret(resource, id, name, component, kind, values) if err != nil { log.Fatalf("Unable to create %s secret: %v", entityKind, err) } if config.Verbose { log.Printf("Secret `%s` created in %s `%s` with id `%s`", name, entityKind, selector, secretId) } if config.Verbose { switch entityKind { case "environment": env, err := environmentById(id) if err == nil { formatEnvironment(env) } case "template": template, err := templateById(id) if err == nil { formatTemplate(template) } case "instance": instance, err := stackInstanceBy(id) if err == nil { formatStackInstance(instance) } } } } func createSecret(resource, id, name, component, kind string, values map[string]string) (string, error) { values["name"] = name if component != "" { values["component"] = component } values["kind"] = kind path := fmt.Sprintf("%s/%s/secrets", resource, url.PathEscape(id)) var jsResp CreateSecretResponse code, err := post(hubApi(), path, values, &jsResp) if err != nil { return "", fmt.Errorf("Error creating HubCTL `%s/%s` Secret `%s`: %v", resource, id, name, err) } if code != 201 { return "", fmt.Errorf("Got %d HTTP creating HubCTL `%s` Secret `%s`, expected 201 HTTP", code, id, name) } return jsResp.Id, nil } func GetSecret(entityKind, selector, uuid string, jsonFormat bool) { if config.Debug { log.Printf("Getting %s/%s secret `%s`", entityKind, selector, uuid) } id := "" resource := "" var qErr error switch entityKind { case "cloudaccount": cloudAccount, err := cloudAccountBy(selector) qErr = err if err == nil && cloudAccount != nil { id = cloudAccount.Id } resource = cloudAccountsResource case "environment": env, err := environmentBy(selector) qErr = err if err == nil && env != nil { id = env.Id } resource = environmentsResource case "template": template, err := templateBy(selector) qErr = err if err == nil && template != nil { id = template.Id } resource = templatesResource case "instance": instance, err := stackInstanceBy(selector) qErr = err if err == nil && instance != nil { id = instance.Id } resource = stackInstancesResource case "application": application, err := applicationBy(selector) qErr = err if err == nil && application != nil { id = application.Id } resource = applicationsResource default: log.Fatalf("Unknown entity kind `%s`", entityKind) } if id == "" && qErr == nil { qErr = errors.New("Not Found") } if qErr != nil { msg := fmt.Sprintf("Unable to query %s %s: %v", entityKind, selector, qErr) if config.Force && util.IsUint(selector) { util.Warn("%s", msg) id = selector } else { log.Fatal(msg) } } resource = fmt.Sprintf("%s/%s", resource, id) resp, err := secret(resource, uuid) if err != nil { log.Fatalf("Unable to get secret: %v", err) } if jsonFormat { out, err := json.MarshalIndent(resp, "", " ") if err != nil { log.Fatalf("Error marshalling JSON response for output: %v", err) } os.Stdout.Write(out) os.Stdout.Write([]byte("\n")) } else { str, kind := formatSecret(resp) if config.Debug { log.Printf("Secret kind: %s", kind) } fmt.Println(str) } } func secret(resource, id string) (map[string]string, error) { path := fmt.Sprintf("%s/secrets/%s", resource, url.PathEscape(id)) var jsResp map[string]string code, err := get(hubApi(), path, &jsResp) if err != nil { return nil, fmt.Errorf("Error querying HubCTL `%s` Secret `%s`: %v", resource, id, err) } if code != 200 { return nil, fmt.Errorf("Got %d HTTP querying HubCTL `%s` Secret `%s`, expected 200 HTTP", code, resource, id) } return jsResp, nil } func formatSecret(s map[string]string) (string, string) { str := "" k := "" if kind, ok := s["kind"]; ok { k = kind switch kind { case "text", "password", "certificate", "sshKey", "privateKey", "token", "bearerToken", "accessToken", "refreshToken", "loginToken": str = s[kind] case "license": str = s["licenseKey"] case "gitAccessToken": // legacy str = s["loginToken"] case "usernamePassword": str = fmt.Sprintf("%s/%s", s["username"], s["password"]) case "cloudAccessKeys": str = fmt.Sprintf("%s:%s", s["accessKey"], s["secretKey"]) case "cloudAccount": str = fmt.Sprintf("%s/%s", s["roleArn"], s["externalId"]) } } if str == "" { str = fmt.Sprintf("%+v", s) } return str, k }