github.com/djenriquez/nomad-1@v0.8.1/command/agent/keyring.go (about)

     1  package agent
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	"github.com/hashicorp/memberlist"
    12  	"github.com/hashicorp/serf/serf"
    13  )
    14  
    15  const (
    16  	serfKeyring = "server/serf.keyring"
    17  )
    18  
    19  // initKeyring will create a keyring file at a given path.
    20  func initKeyring(path, key string) error {
    21  	var keys []string
    22  
    23  	if keyBytes, err := base64.StdEncoding.DecodeString(key); err != nil {
    24  		return fmt.Errorf("Invalid key: %s", err)
    25  	} else if err := memberlist.ValidateKey(keyBytes); err != nil {
    26  		return fmt.Errorf("Invalid key: %s", err)
    27  	}
    28  
    29  	// Just exit if the file already exists.
    30  	if _, err := os.Stat(path); err == nil {
    31  		return nil
    32  	}
    33  
    34  	keys = append(keys, key)
    35  	keyringBytes, err := json.Marshal(keys)
    36  	if err != nil {
    37  		return err
    38  	}
    39  
    40  	if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
    41  		return err
    42  	}
    43  
    44  	fh, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
    45  	if err != nil {
    46  		return err
    47  	}
    48  	defer fh.Close()
    49  
    50  	if _, err := fh.Write(keyringBytes); err != nil {
    51  		os.Remove(path)
    52  		return err
    53  	}
    54  
    55  	return nil
    56  }
    57  
    58  // loadKeyringFile will load a gossip encryption keyring out of a file. The file
    59  // must be in JSON format and contain a list of encryption key strings.
    60  func loadKeyringFile(c *serf.Config) error {
    61  	if c.KeyringFile == "" {
    62  		return nil
    63  	}
    64  
    65  	if _, err := os.Stat(c.KeyringFile); err != nil {
    66  		return err
    67  	}
    68  
    69  	// Read in the keyring file data
    70  	keyringData, err := ioutil.ReadFile(c.KeyringFile)
    71  	if err != nil {
    72  		return err
    73  	}
    74  
    75  	// Decode keyring JSON
    76  	keys := make([]string, 0)
    77  	if err := json.Unmarshal(keyringData, &keys); err != nil {
    78  		return err
    79  	}
    80  
    81  	// Decode base64 values
    82  	keysDecoded := make([][]byte, len(keys))
    83  	for i, key := range keys {
    84  		keyBytes, err := base64.StdEncoding.DecodeString(key)
    85  		if err != nil {
    86  			return err
    87  		}
    88  		keysDecoded[i] = keyBytes
    89  	}
    90  
    91  	// Guard against empty keyring
    92  	if len(keysDecoded) == 0 {
    93  		return fmt.Errorf("no keys present in keyring file: %s", c.KeyringFile)
    94  	}
    95  
    96  	// Create the keyring
    97  	keyring, err := memberlist.NewKeyring(keysDecoded, keysDecoded[0])
    98  	if err != nil {
    99  		return err
   100  	}
   101  
   102  	c.MemberlistConfig.Keyring = keyring
   103  
   104  	// Success!
   105  	return nil
   106  }