Signed-off-by: Daniel Nephin <dnephin@docker.com>
| ... | ... |
@@ -1,17 +1,5 @@ |
| 1 | 1 |
package api |
| 2 | 2 |
|
| 3 |
-import ( |
|
| 4 |
- "encoding/json" |
|
| 5 |
- "encoding/pem" |
|
| 6 |
- "fmt" |
|
| 7 |
- "os" |
|
| 8 |
- "path/filepath" |
|
| 9 |
- |
|
| 10 |
- "github.com/docker/docker/pkg/ioutils" |
|
| 11 |
- "github.com/docker/docker/pkg/system" |
|
| 12 |
- "github.com/docker/libtrust" |
|
| 13 |
-) |
|
| 14 |
- |
|
| 15 | 3 |
// Common constants for daemon and client. |
| 16 | 4 |
const ( |
| 17 | 5 |
// DefaultVersion of Current REST API |
| ... | ... |
@@ -21,45 +9,3 @@ const ( |
| 21 | 21 |
// command to specify that no base image is to be used. |
| 22 | 22 |
NoBaseImageSpecifier string = "scratch" |
| 23 | 23 |
) |
| 24 |
- |
|
| 25 |
-// LoadOrCreateTrustKey attempts to load the libtrust key at the given path, |
|
| 26 |
-// otherwise generates a new one |
|
| 27 |
-func LoadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) {
|
|
| 28 |
- err := system.MkdirAll(filepath.Dir(trustKeyPath), 0700, "") |
|
| 29 |
- if err != nil {
|
|
| 30 |
- return nil, err |
|
| 31 |
- } |
|
| 32 |
- trustKey, err := libtrust.LoadKeyFile(trustKeyPath) |
|
| 33 |
- if err == libtrust.ErrKeyFileDoesNotExist {
|
|
| 34 |
- trustKey, err = libtrust.GenerateECP256PrivateKey() |
|
| 35 |
- if err != nil {
|
|
| 36 |
- return nil, fmt.Errorf("Error generating key: %s", err)
|
|
| 37 |
- } |
|
| 38 |
- encodedKey, err := serializePrivateKey(trustKey, filepath.Ext(trustKeyPath)) |
|
| 39 |
- if err != nil {
|
|
| 40 |
- return nil, fmt.Errorf("Error serializing key: %s", err)
|
|
| 41 |
- } |
|
| 42 |
- if err := ioutils.AtomicWriteFile(trustKeyPath, encodedKey, os.FileMode(0600)); err != nil {
|
|
| 43 |
- return nil, fmt.Errorf("Error saving key file: %s", err)
|
|
| 44 |
- } |
|
| 45 |
- } else if err != nil {
|
|
| 46 |
- return nil, fmt.Errorf("Error loading key file %s: %s", trustKeyPath, err)
|
|
| 47 |
- } |
|
| 48 |
- return trustKey, nil |
|
| 49 |
-} |
|
| 50 |
- |
|
| 51 |
-func serializePrivateKey(key libtrust.PrivateKey, ext string) (encoded []byte, err error) {
|
|
| 52 |
- if ext == ".json" || ext == ".jwk" {
|
|
| 53 |
- encoded, err = json.Marshal(key) |
|
| 54 |
- if err != nil {
|
|
| 55 |
- return nil, fmt.Errorf("unable to encode private key JWK: %s", err)
|
|
| 56 |
- } |
|
| 57 |
- } else {
|
|
| 58 |
- pemBlock, err := key.PEMBlock() |
|
| 59 |
- if err != nil {
|
|
| 60 |
- return nil, fmt.Errorf("unable to encode private key PEM: %s", err)
|
|
| 61 |
- } |
|
| 62 |
- encoded = pem.EncodeToMemory(pemBlock) |
|
| 63 |
- } |
|
| 64 |
- return |
|
| 65 |
-} |
| 66 | 24 |
deleted file mode 100644 |
| ... | ... |
@@ -1,77 +0,0 @@ |
| 1 |
-package api |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "io/ioutil" |
|
| 5 |
- "path/filepath" |
|
| 6 |
- "testing" |
|
| 7 |
- |
|
| 8 |
- "os" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-// LoadOrCreateTrustKey |
|
| 12 |
-func TestLoadOrCreateTrustKeyInvalidKeyFile(t *testing.T) {
|
|
| 13 |
- tmpKeyFolderPath, err := ioutil.TempDir("", "api-trustkey-test")
|
|
| 14 |
- if err != nil {
|
|
| 15 |
- t.Fatal(err) |
|
| 16 |
- } |
|
| 17 |
- defer os.RemoveAll(tmpKeyFolderPath) |
|
| 18 |
- |
|
| 19 |
- tmpKeyFile, err := ioutil.TempFile(tmpKeyFolderPath, "keyfile") |
|
| 20 |
- if err != nil {
|
|
| 21 |
- t.Fatal(err) |
|
| 22 |
- } |
|
| 23 |
- |
|
| 24 |
- if _, err := LoadOrCreateTrustKey(tmpKeyFile.Name()); err == nil {
|
|
| 25 |
- t.Fatal("expected an error, got nothing.")
|
|
| 26 |
- } |
|
| 27 |
- |
|
| 28 |
-} |
|
| 29 |
- |
|
| 30 |
-func TestLoadOrCreateTrustKeyCreateKey(t *testing.T) {
|
|
| 31 |
- tmpKeyFolderPath, err := ioutil.TempDir("", "api-trustkey-test")
|
|
| 32 |
- if err != nil {
|
|
| 33 |
- t.Fatal(err) |
|
| 34 |
- } |
|
| 35 |
- defer os.RemoveAll(tmpKeyFolderPath) |
|
| 36 |
- |
|
| 37 |
- // Without the need to create the folder hierarchy |
|
| 38 |
- tmpKeyFile := filepath.Join(tmpKeyFolderPath, "keyfile") |
|
| 39 |
- |
|
| 40 |
- if key, err := LoadOrCreateTrustKey(tmpKeyFile); err != nil || key == nil {
|
|
| 41 |
- t.Fatalf("expected a new key file, got : %v and %v", err, key)
|
|
| 42 |
- } |
|
| 43 |
- |
|
| 44 |
- if _, err := os.Stat(tmpKeyFile); err != nil {
|
|
| 45 |
- t.Fatalf("Expected to find a file %s, got %v", tmpKeyFile, err)
|
|
| 46 |
- } |
|
| 47 |
- |
|
| 48 |
- // With the need to create the folder hierarchy as tmpKeyFie is in a path |
|
| 49 |
- // where some folders do not exist. |
|
| 50 |
- tmpKeyFile = filepath.Join(tmpKeyFolderPath, "folder/hierarchy/keyfile") |
|
| 51 |
- |
|
| 52 |
- if key, err := LoadOrCreateTrustKey(tmpKeyFile); err != nil || key == nil {
|
|
| 53 |
- t.Fatalf("expected a new key file, got : %v and %v", err, key)
|
|
| 54 |
- } |
|
| 55 |
- |
|
| 56 |
- if _, err := os.Stat(tmpKeyFile); err != nil {
|
|
| 57 |
- t.Fatalf("Expected to find a file %s, got %v", tmpKeyFile, err)
|
|
| 58 |
- } |
|
| 59 |
- |
|
| 60 |
- // With no path at all |
|
| 61 |
- defer os.Remove("keyfile")
|
|
| 62 |
- if key, err := LoadOrCreateTrustKey("keyfile"); err != nil || key == nil {
|
|
| 63 |
- t.Fatalf("expected a new key file, got : %v and %v", err, key)
|
|
| 64 |
- } |
|
| 65 |
- |
|
| 66 |
- if _, err := os.Stat("keyfile"); err != nil {
|
|
| 67 |
- t.Fatalf("Expected to find a file keyfile, got %v", err)
|
|
| 68 |
- } |
|
| 69 |
-} |
|
| 70 |
- |
|
| 71 |
-func TestLoadOrCreateTrustKeyLoadValidKey(t *testing.T) {
|
|
| 72 |
- tmpKeyFile := filepath.Join("fixtures", "keyfile")
|
|
| 73 |
- |
|
| 74 |
- if key, err := LoadOrCreateTrustKey(tmpKeyFile); err != nil || key == nil {
|
|
| 75 |
- t.Fatalf("expected a key file, got : %v and %v", err, key)
|
|
| 76 |
- } |
|
| 77 |
-} |
| 78 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,7 +0,0 @@ |
| 1 |
-keyID: AWX2:I27X:WQFX:IOMK:CNAK:O7PW:VYNB:ZLKC:CVAE:YJP2:SI4A:XXAY |
|
| 2 |
- |
|
| 3 |
-MHcCAQEEILHTRWdcpKWsnORxSFyBnndJ4ROU41hMtr/GCiLVvwBQoAoGCCqGSM49 |
|
| 4 |
-AwEHoUQDQgAElpVFbQ2V2UQKajqdE3fVxJ+/pE/YuEFOxWbOxF2be19BY209/iky |
|
| 5 |
-NzeFFK7SLpQ4CBJ7zDVXOHsMzrkY/GquGA== |
| ... | ... |
@@ -19,7 +19,6 @@ import ( |
| 19 | 19 |
"time" |
| 20 | 20 |
|
| 21 | 21 |
containerd "github.com/containerd/containerd/api/grpc/types" |
| 22 |
- "github.com/docker/docker/api" |
|
| 23 | 22 |
"github.com/docker/docker/api/types" |
| 24 | 23 |
containertypes "github.com/docker/docker/api/types/container" |
| 25 | 24 |
"github.com/docker/docker/api/types/swarm" |
| ... | ... |
@@ -713,7 +712,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe |
| 713 | 713 |
return nil, err |
| 714 | 714 |
} |
| 715 | 715 |
|
| 716 |
- trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath) |
|
| 716 |
+ trustKey, err := loadOrCreateTrustKey(config.TrustKeyPath) |
|
| 717 | 717 |
if err != nil {
|
| 718 | 718 |
return nil, err |
| 719 | 719 |
} |
| 720 | 720 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,7 @@ |
| 0 |
+-----BEGIN EC PRIVATE KEY----- |
|
| 1 |
+keyID: AWX2:I27X:WQFX:IOMK:CNAK:O7PW:VYNB:ZLKC:CVAE:YJP2:SI4A:XXAY |
|
| 2 |
+ |
|
| 3 |
+MHcCAQEEILHTRWdcpKWsnORxSFyBnndJ4ROU41hMtr/GCiLVvwBQoAoGCCqGSM49 |
|
| 4 |
+AwEHoUQDQgAElpVFbQ2V2UQKajqdE3fVxJ+/pE/YuEFOxWbOxF2be19BY209/iky |
|
| 5 |
+NzeFFK7SLpQ4CBJ7zDVXOHsMzrkY/GquGA== |
|
| 6 |
+-----END EC PRIVATE KEY----- |
| 0 | 7 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,57 @@ |
| 0 |
+package daemon |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/json" |
|
| 4 |
+ "encoding/pem" |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "os" |
|
| 7 |
+ "path/filepath" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/docker/docker/pkg/ioutils" |
|
| 10 |
+ "github.com/docker/docker/pkg/system" |
|
| 11 |
+ "github.com/docker/libtrust" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+// LoadOrCreateTrustKey attempts to load the libtrust key at the given path, |
|
| 15 |
+// otherwise generates a new one |
|
| 16 |
+// TODO: this should use more of libtrust.LoadOrCreateTrustKey which may need |
|
| 17 |
+// a refactor or this function to be moved into libtrust |
|
| 18 |
+func loadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) {
|
|
| 19 |
+ err := system.MkdirAll(filepath.Dir(trustKeyPath), 0700, "") |
|
| 20 |
+ if err != nil {
|
|
| 21 |
+ return nil, err |
|
| 22 |
+ } |
|
| 23 |
+ trustKey, err := libtrust.LoadKeyFile(trustKeyPath) |
|
| 24 |
+ if err == libtrust.ErrKeyFileDoesNotExist {
|
|
| 25 |
+ trustKey, err = libtrust.GenerateECP256PrivateKey() |
|
| 26 |
+ if err != nil {
|
|
| 27 |
+ return nil, fmt.Errorf("Error generating key: %s", err)
|
|
| 28 |
+ } |
|
| 29 |
+ encodedKey, err := serializePrivateKey(trustKey, filepath.Ext(trustKeyPath)) |
|
| 30 |
+ if err != nil {
|
|
| 31 |
+ return nil, fmt.Errorf("Error serializing key: %s", err)
|
|
| 32 |
+ } |
|
| 33 |
+ if err := ioutils.AtomicWriteFile(trustKeyPath, encodedKey, os.FileMode(0600)); err != nil {
|
|
| 34 |
+ return nil, fmt.Errorf("Error saving key file: %s", err)
|
|
| 35 |
+ } |
|
| 36 |
+ } else if err != nil {
|
|
| 37 |
+ return nil, fmt.Errorf("Error loading key file %s: %s", trustKeyPath, err)
|
|
| 38 |
+ } |
|
| 39 |
+ return trustKey, nil |
|
| 40 |
+} |
|
| 41 |
+ |
|
| 42 |
+func serializePrivateKey(key libtrust.PrivateKey, ext string) (encoded []byte, err error) {
|
|
| 43 |
+ if ext == ".json" || ext == ".jwk" {
|
|
| 44 |
+ encoded, err = json.Marshal(key) |
|
| 45 |
+ if err != nil {
|
|
| 46 |
+ return nil, fmt.Errorf("unable to encode private key JWK: %s", err)
|
|
| 47 |
+ } |
|
| 48 |
+ } else {
|
|
| 49 |
+ pemBlock, err := key.PEMBlock() |
|
| 50 |
+ if err != nil {
|
|
| 51 |
+ return nil, fmt.Errorf("unable to encode private key PEM: %s", err)
|
|
| 52 |
+ } |
|
| 53 |
+ encoded = pem.EncodeToMemory(pemBlock) |
|
| 54 |
+ } |
|
| 55 |
+ return |
|
| 56 |
+} |
| 0 | 57 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,72 @@ |
| 0 |
+package daemon |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "io/ioutil" |
|
| 4 |
+ "os" |
|
| 5 |
+ "path/filepath" |
|
| 6 |
+ "testing" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/docker/docker/internal/testutil" |
|
| 9 |
+ "github.com/gotestyourself/gotestyourself/fs" |
|
| 10 |
+ "github.com/stretchr/testify/assert" |
|
| 11 |
+ "github.com/stretchr/testify/require" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+// LoadOrCreateTrustKey |
|
| 15 |
+func TestLoadOrCreateTrustKeyInvalidKeyFile(t *testing.T) {
|
|
| 16 |
+ tmpKeyFolderPath, err := ioutil.TempDir("", "api-trustkey-test")
|
|
| 17 |
+ require.NoError(t, err) |
|
| 18 |
+ defer os.RemoveAll(tmpKeyFolderPath) |
|
| 19 |
+ |
|
| 20 |
+ tmpKeyFile, err := ioutil.TempFile(tmpKeyFolderPath, "keyfile") |
|
| 21 |
+ require.NoError(t, err) |
|
| 22 |
+ |
|
| 23 |
+ _, err = loadOrCreateTrustKey(tmpKeyFile.Name()) |
|
| 24 |
+ testutil.ErrorContains(t, err, "Error loading key file") |
|
| 25 |
+} |
|
| 26 |
+ |
|
| 27 |
+func TestLoadOrCreateTrustKeyCreateKeyWhenFileDoesNotExist(t *testing.T) {
|
|
| 28 |
+ tmpKeyFolderPath := fs.NewDir(t, "api-trustkey-test") |
|
| 29 |
+ defer tmpKeyFolderPath.Remove() |
|
| 30 |
+ |
|
| 31 |
+ // Without the need to create the folder hierarchy |
|
| 32 |
+ tmpKeyFile := tmpKeyFolderPath.Join("keyfile")
|
|
| 33 |
+ |
|
| 34 |
+ key, err := loadOrCreateTrustKey(tmpKeyFile) |
|
| 35 |
+ require.NoError(t, err) |
|
| 36 |
+ assert.NotNil(t, key) |
|
| 37 |
+ |
|
| 38 |
+ _, err = os.Stat(tmpKeyFile) |
|
| 39 |
+ require.NoError(t, err, "key file doesn't exist") |
|
| 40 |
+} |
|
| 41 |
+ |
|
| 42 |
+func TestLoadOrCreateTrustKeyCreateKeyWhenDirectoryDoesNotExist(t *testing.T) {
|
|
| 43 |
+ tmpKeyFolderPath := fs.NewDir(t, "api-trustkey-test") |
|
| 44 |
+ defer tmpKeyFolderPath.Remove() |
|
| 45 |
+ tmpKeyFile := tmpKeyFolderPath.Join("folder/hierarchy/keyfile")
|
|
| 46 |
+ |
|
| 47 |
+ key, err := loadOrCreateTrustKey(tmpKeyFile) |
|
| 48 |
+ require.NoError(t, err) |
|
| 49 |
+ assert.NotNil(t, key) |
|
| 50 |
+ |
|
| 51 |
+ _, err = os.Stat(tmpKeyFile) |
|
| 52 |
+ require.NoError(t, err, "key file doesn't exist") |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+func TestLoadOrCreateTrustKeyCreateKeyNoPath(t *testing.T) {
|
|
| 56 |
+ defer os.Remove("keyfile")
|
|
| 57 |
+ key, err := loadOrCreateTrustKey("keyfile")
|
|
| 58 |
+ require.NoError(t, err) |
|
| 59 |
+ assert.NotNil(t, key) |
|
| 60 |
+ |
|
| 61 |
+ _, err = os.Stat("keyfile")
|
|
| 62 |
+ require.NoError(t, err, "key file doesn't exist") |
|
| 63 |
+} |
|
| 64 |
+ |
|
| 65 |
+func TestLoadOrCreateTrustKeyLoadValidKey(t *testing.T) {
|
|
| 66 |
+ tmpKeyFile := filepath.Join("testdata", "keyfile")
|
|
| 67 |
+ key, err := loadOrCreateTrustKey(tmpKeyFile) |
|
| 68 |
+ require.NoError(t, err) |
|
| 69 |
+ expected := "AWX2:I27X:WQFX:IOMK:CNAK:O7PW:VYNB:ZLKC:CVAE:YJP2:SI4A:XXAY" |
|
| 70 |
+ assert.Contains(t, key.String(), expected) |
|
| 71 |
+} |