github.com/yggdrasil-network/yggdrasil-go@v0.5.6/contrib/ansible/genkeys.go (about)

     1  /*
     2  This file generates crypto keys for [ansible-yggdrasil](https://github.com/jcgruenhage/ansible-yggdrasil/)
     3  */
     4  package main
     5  
     6  import (
     7  	"crypto/ed25519"
     8  	"encoding/hex"
     9  	"flag"
    10  	"fmt"
    11  	"net"
    12  	"os"
    13  
    14  	"github.com/cheggaaa/pb/v3"
    15  	"github.com/yggdrasil-network/yggdrasil-go/src/address"
    16  )
    17  
    18  var numHosts = flag.Int("hosts", 1, "number of host vars to generate")
    19  var keyTries = flag.Int("tries", 1000, "number of tries before taking the best keys")
    20  
    21  type keySet struct {
    22  	priv []byte
    23  	pub  []byte
    24  	ip   string
    25  }
    26  
    27  func main() {
    28  	flag.Parse()
    29  
    30  	bar := pb.StartNew(*keyTries*2 + *numHosts)
    31  
    32  	if *numHosts > *keyTries {
    33  		println("Can't generate less keys than hosts.")
    34  		return
    35  	}
    36  
    37  	var keys []keySet
    38  	for i := 0; i < *numHosts+1; i++ {
    39  		keys = append(keys, newKey())
    40  		bar.Increment()
    41  	}
    42  	keys = sortKeySetArray(keys)
    43  	for i := 0; i < *keyTries-*numHosts-1; i++ {
    44  		keys[0] = newKey()
    45  		keys = bubbleUpTo(keys, 0)
    46  		bar.Increment()
    47  	}
    48  
    49  	os.MkdirAll("host_vars", 0755)
    50  
    51  	for i := 1; i <= *numHosts; i++ {
    52  		os.MkdirAll(fmt.Sprintf("host_vars/%x", i), 0755)
    53  		file, err := os.Create(fmt.Sprintf("host_vars/%x/vars", i))
    54  		if err != nil {
    55  			return
    56  		}
    57  		defer file.Close()
    58  		file.WriteString(fmt.Sprintf("yggdrasil_public_key: %v\n", hex.EncodeToString(keys[i].pub)))
    59  		file.WriteString("yggdrasil_private_key: \"{{ vault_yggdrasil_private_key }}\"\n")
    60  		file.WriteString(fmt.Sprintf("ansible_host: %v\n", keys[i].ip))
    61  
    62  		file, err = os.Create(fmt.Sprintf("host_vars/%x/vault", i))
    63  		if err != nil {
    64  			return
    65  		}
    66  		defer file.Close()
    67  		file.WriteString(fmt.Sprintf("vault_yggdrasil_private_key: %v\n", hex.EncodeToString(keys[i].priv)))
    68  		bar.Increment()
    69  	}
    70  	bar.Finish()
    71  }
    72  
    73  func newKey() keySet {
    74  	pub, priv, err := ed25519.GenerateKey(nil)
    75  	if err != nil {
    76  		panic(err)
    77  	}
    78  	ip := net.IP(address.AddrForKey(pub)[:]).String()
    79  	return keySet{priv[:], pub[:], ip}
    80  }
    81  
    82  func isBetter(oldID, newID []byte) bool {
    83  	for idx := range oldID {
    84  		if newID[idx] < oldID[idx] {
    85  			return true
    86  		}
    87  		if newID[idx] > oldID[idx] {
    88  			return false
    89  		}
    90  	}
    91  	return false
    92  }
    93  
    94  func sortKeySetArray(sets []keySet) []keySet {
    95  	for i := 0; i < len(sets); i++ {
    96  		sets = bubbleUpTo(sets, i)
    97  	}
    98  	return sets
    99  }
   100  
   101  func bubbleUpTo(sets []keySet, num int) []keySet {
   102  	for i := 0; i < len(sets)-num-1; i++ {
   103  		if isBetter(sets[i+1].pub, sets[i].pub) {
   104  			var tmp = sets[i]
   105  			sets[i] = sets[i+1]
   106  			sets[i+1] = tmp
   107  		} else {
   108  			break
   109  		}
   110  	}
   111  	return sets
   112  }