同时遍历Hashicorp Vault

问题描述

我正在尝试同时通过Vault服务器。我可以递归搜索,但是无法并行化它。

下面是我想出的代码示例。我正在研究如何通过使用并发来使其更快。是否可以同时遍历保险柜路径?

package main

import (
    "flag"
    "fmt"
    "github.com/hashicorp/vault/api"
    "log"
    "net/http"
    "strings"
    "sync"
    "time"
)

var vault_path string
var vault_addr string

var dev_vault_addr = ""
var pie_vault_addr = ""
var prod_vault_addr = ""

var dev_vault_path string = ""
var pie_vault_path string = ""
var prod_vault_path string = ""

//flags
var env = flag.String("ENV","","vault environment - dev,pie,prod")
var okta_user = flag.String("USER","okta username")
var okta_pw = flag.String("PW","okta pw")
var searchValue= flag.String("VALUE","value to search for")
var searchKey = flag.String("KEY","key to search for")

func main() {
    flag.Parse()
    switch *env {
    case "dev":
        fmt.Println("dev vault ")
        vault_path = dev_vault_path
        vault_addr = dev_vault_addr
    case "pie":
        fmt.Println("pie")
        vault_path = pie_vault_path
        vault_addr = pie_vault_addr
    case "prod":
        fmt.Println("prod")
        vault_path = prod_vault_path
        vault_addr = prod_vault_addr
    }
    workerCount := 1
    jobs := make(chan workerJob,workerCount)
    results := make(chan workerResult)
    readDone := make(chan bool)
    wg := &sync.WaitGroup{}
    // start N workers

    for i := 0; i < workerCount; i++ {
        go worker(jobs,results,wg)
    }

    // One initial job
    wg.Add(1)
    go func() {
        jobs <- workerJob{
            Path: vault_path,}
    }()

    // When all jobs finished,shutdown the system.
    go func() {
        wg.Wait()
        readDone <- true
    }()

readloop:
    for {
        select {
        case res := <-results:
            log.Printf(`result=%#v`,res.secret)
        case <-readDone:
            log.Printf(`got stop`)
            close(jobs)
            break readloop
        }
    }
}
func setupClient(vault_addr string) *api.Client {
    httpClient := &http.Client{
        Timeout: 10 * time.Second,}
    client,err := api.NewClient(&api.Config{Address: vault_addr,HttpClient: httpClient})
    if err != nil {
        fmt.Println(err)
    }
    // to pass the password
    options := map[string]interface{}{
        "password": okta_pw,}

    // the login path
    // this is configurable,change userpass to ldap etc
    path := fmt.Sprintf("auth/okta/login/%s",*okta_user)


    // PUT call to get a token
    secret,err := client.Logical().Write(path,options)
    client.SetToken(secret.Auth.ClientToken)
    return client
}

func walkDir(client *api.Client,path string) {
    var value *api.Secret
    var err error
    if path != "" {
        value,err = client.Logical().List(path)
    } else {
        path = vault_path
        value,err = client.Logical().List(path)
    }
    if err != nil {
        fmt.Println(err)
    }
    var datamap map[string]interface{}
    datamap = value.Data
    data := datamap["keys"].([]interface{})

    for _,item := range data {
        itemString := item.(string)
        if strings.HasSuffix(itemString,"/") {
            walkDir(client,path+itemString)
        } else {
            //its a secret
            data := read(client,path+itemString)

            if *searchKey!="" && searchForKey(data,*searchKey){
                fmt.Println(path + itemString)
            }
            if *searchValue!="" && searchForValue(data,*searchValue){
                fmt.Println(path + itemString)
            }
        }
    }
}

func read(client *api.Client,path string) map[string]interface{} {
    value,err := client.Logical().Read(path)
    if err != nil {
        fmt.Println(err)
    }
    values := value.Data
    return values
}

func searchForValue(mapp map[string]interface{},searchValue string) bool {
    for _,value := range mapp {
        if searchValue == value {
            return true
        }
    }
    return false
}

func searchForKey(mapp map[string]interface{},searchKey string) bool {
    for key := range mapp {
        if searchKey == key {
            return true
        }
    }
    return false
}


// Job for worker
type workerJob struct {
    Address string
    Path string
}

// Result of a worker
type workerResult struct {
    secret map[string]interface{}
}

func worker(jobs chan workerJob,results chan<- workerResult,wg *sync.WaitGroup) {
    for j := range jobs {
        client := setupClient(vault_addr)
        log.Printf(`Vault Path: %#v`,j.Path)
        var value *api.Secret
        if j.Path != "" {
            value,_ = client.Logical().List(j.Path)
        } else {
            j.Path = vault_path
            value,_ = client.Logical().List(j.Path)
        }

        var datamap map[string]interface{}
        datamap = value.Data
        data := datamap["keys"].([]interface{})

        for _,item := range data {
            itemString := item.(string)
            if strings.HasSuffix(itemString,"/") {
                nj := workerJob{Path: itemString}
                log.Printf(`sent new vault dir job: %#v`,nj.Path)
                //one more job add to wg
                wg.Add(1)
                // Do not block when sending jobs
                go func() {
                    jobs <- nj
                }()
            } else {
                //its a secret
                data := read(client,j.Path+itemString)
                if *searchKey!="" && searchForKey(data,*searchKey){
                    log.Printf(vault_path+itemString)
                    r := workerResult{
                        secret: data,}
                    results<-r
                }
                if *searchValue!="" && searchForValue(data,*searchValue){
                    log.Printf(vault_path+itemString)
                    r := workerResult{
                        secret: data,}
                    results<-r
                }


            }
        }
        // Done one job,let wg kNow.
        wg.Done()
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)