mirror of https://github.com/k3s-io/k3s
Darren Shepherd
5 years ago
10 changed files with 251 additions and 57 deletions
@ -0,0 +1,81 @@
|
||||
package cluster |
||||
|
||||
import ( |
||||
"crypto/aes" |
||||
"crypto/cipher" |
||||
"crypto/rand" |
||||
"crypto/sha1" |
||||
"crypto/sha256" |
||||
"encoding/base64" |
||||
"encoding/hex" |
||||
"fmt" |
||||
"io" |
||||
"strings" |
||||
|
||||
"github.com/rancher/k3s/pkg/token" |
||||
"golang.org/x/crypto/pbkdf2" |
||||
) |
||||
|
||||
func storageKey(passphrase string) string { |
||||
d := sha256.New() |
||||
d.Write([]byte(passphrase)) |
||||
return "/bootstrap/" + hex.EncodeToString(d.Sum(nil)[:])[:12] |
||||
} |
||||
|
||||
func keyHash(passphrase string) string { |
||||
d := sha256.New() |
||||
d.Write([]byte(passphrase)) |
||||
return hex.EncodeToString(d.Sum(nil)[:])[:12] |
||||
} |
||||
|
||||
func encrypt(passphrase string, plaintext []byte) ([]byte, error) { |
||||
salt, err := token.Random(8) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
clearKey := pbkdf2.Key([]byte(passphrase), []byte(salt), 4096, 32, sha1.New) |
||||
key, err := aes.NewCipher(clearKey) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
gcm, err := cipher.NewGCM(key) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
nonce := make([]byte, gcm.NonceSize()) |
||||
_, err = io.ReadFull(rand.Reader, nonce) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
sealed := gcm.Seal(nonce, nonce, plaintext, nil) |
||||
return []byte(salt + ":" + base64.StdEncoding.EncodeToString(sealed)), nil |
||||
} |
||||
|
||||
func decrypt(passphrase string, ciphertext []byte) ([]byte, error) { |
||||
parts := strings.SplitN(string(ciphertext), ":", 2) |
||||
if len(parts) != 2 { |
||||
return nil, fmt.Errorf("invalid cipher text, not : delimited") |
||||
} |
||||
|
||||
clearKey := pbkdf2.Key([]byte(passphrase), []byte(parts[0]), 4096, 32, sha1.New) |
||||
key, err := aes.NewCipher(clearKey) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
gcm, err := cipher.NewGCM(key) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
data, err := base64.StdEncoding.DecodeString(parts[1]) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return gcm.Open(nil, data[:gcm.NonceSize()], data[gcm.NonceSize():], nil) |
||||
} |
@ -0,0 +1,50 @@
|
||||
package cluster |
||||
|
||||
import ( |
||||
"bytes" |
||||
"context" |
||||
|
||||
"github.com/rancher/k3s/pkg/bootstrap" |
||||
"github.com/rancher/kine/pkg/client" |
||||
) |
||||
|
||||
func (c *Cluster) save(ctx context.Context) error { |
||||
buf := &bytes.Buffer{} |
||||
if err := bootstrap.Write(buf, &c.runtime.ControlRuntimeBootstrap); err != nil { |
||||
return err |
||||
} |
||||
|
||||
data, err := encrypt(c.config.Token, buf.Bytes()) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
return c.storageClient.Create(ctx, storageKey(c.config.Token), data) |
||||
} |
||||
|
||||
func (c *Cluster) storageJoin(ctx context.Context) error { |
||||
if err := c.startStorage(ctx); err != nil { |
||||
return err |
||||
} |
||||
|
||||
storageClient, err := client.New(c.etcdConfig) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
c.storageClient = storageClient |
||||
|
||||
value, err := storageClient.Get(ctx, storageKey(c.config.Token)) |
||||
if err == client.ErrNotFound { |
||||
c.saveBootstrap = true |
||||
return nil |
||||
} else if err != nil { |
||||
return err |
||||
} |
||||
|
||||
data, err := decrypt(c.config.Token, value.Data) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
return bootstrap.Read(bytes.NewBuffer(data), &c.runtime.ControlRuntimeBootstrap) |
||||
} |
Loading…
Reference in new issue