util.go raw

   1  package internal
   2  
   3  import (
   4  	"bytes"
   5  	"crypto/tls"
   6  	"crypto/x509"
   7  	"fmt"
   8  	"io/ioutil"
   9  	"os"
  10  	"reflect"
  11  	"strings"
  12  
  13  	"github.com/mitchellh/go-homedir"
  14  )
  15  
  16  // RemainingKeys will inspect a struct and compare it to a map. Any struct
  17  // field that does not have a JSON tag that matches a key in the map or
  18  // a matching lower-case field in the map will be returned as an extra.
  19  //
  20  // This is useful for determining the extra fields returned in response bodies
  21  // for resources that can contain an arbitrary or dynamic number of fields.
  22  func RemainingKeys(s interface{}, m map[string]interface{}) (extras map[string]interface{}) {
  23  	extras = make(map[string]interface{})
  24  	for k, v := range m {
  25  		extras[k] = v
  26  	}
  27  
  28  	valueOf := reflect.ValueOf(s)
  29  	typeOf := reflect.TypeOf(s)
  30  	for i := 0; i < valueOf.NumField(); i++ {
  31  		field := typeOf.Field(i)
  32  
  33  		lowerField := strings.ToLower(field.Name)
  34  		delete(extras, lowerField)
  35  
  36  		if tagValue := field.Tag.Get("json"); tagValue != "" && tagValue != "-" {
  37  			delete(extras, tagValue)
  38  		}
  39  	}
  40  
  41  	return
  42  }
  43  
  44  // PrepareTLSConfig generates TLS config based on the specifed parameters
  45  func PrepareTLSConfig(caCertFile, clientCertFile, clientKeyFile string, insecure *bool) (*tls.Config, error) {
  46  	config := &tls.Config{}
  47  	if caCertFile != "" {
  48  		caCert, _, err := pathOrContents(caCertFile)
  49  		if err != nil {
  50  			return nil, fmt.Errorf("Error reading CA Cert: %s", err)
  51  		}
  52  
  53  		caCertPool := x509.NewCertPool()
  54  		if ok := caCertPool.AppendCertsFromPEM(bytes.TrimSpace(caCert)); !ok {
  55  			return nil, fmt.Errorf("Error parsing CA Cert from %s", caCertFile)
  56  		}
  57  		config.RootCAs = caCertPool
  58  	}
  59  
  60  	if insecure == nil {
  61  		config.InsecureSkipVerify = false
  62  	} else {
  63  		config.InsecureSkipVerify = *insecure
  64  	}
  65  
  66  	if clientCertFile != "" && clientKeyFile != "" {
  67  		clientCert, _, err := pathOrContents(clientCertFile)
  68  		if err != nil {
  69  			return nil, fmt.Errorf("Error reading Client Cert: %s", err)
  70  		}
  71  		clientKey, _, err := pathOrContents(clientKeyFile)
  72  		if err != nil {
  73  			return nil, fmt.Errorf("Error reading Client Key: %s", err)
  74  		}
  75  
  76  		cert, err := tls.X509KeyPair(clientCert, clientKey)
  77  		if err != nil {
  78  			return nil, err
  79  		}
  80  
  81  		config.Certificates = []tls.Certificate{cert}
  82  		config.BuildNameToCertificate()
  83  	}
  84  
  85  	return config, nil
  86  }
  87  
  88  func pathOrContents(poc string) ([]byte, bool, error) {
  89  	if len(poc) == 0 {
  90  		return nil, false, nil
  91  	}
  92  
  93  	path := poc
  94  	if path[0] == '~' {
  95  		var err error
  96  		path, err = homedir.Expand(path)
  97  		if err != nil {
  98  			return []byte(path), true, err
  99  		}
 100  	}
 101  
 102  	if _, err := os.Stat(path); err == nil {
 103  		contents, err := ioutil.ReadFile(path)
 104  		if err != nil {
 105  			return contents, true, err
 106  		}
 107  		return contents, true, nil
 108  	}
 109  
 110  	return []byte(poc), false, nil
 111  }
 112