Signed-off-by: Victor Vieux <vieux@docker.com>
| ... | ... |
@@ -68,7 +68,7 @@ func LoadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) {
|
| 68 | 68 |
return nil, fmt.Errorf("Error saving key file: %s", err)
|
| 69 | 69 |
} |
| 70 | 70 |
} else if err != nil {
|
| 71 |
- log.Fatalf("Error loading key file: %s", err)
|
|
| 71 |
+ return nil, fmt.Errorf("Error loading key file: %s", err)
|
|
| 72 | 72 |
} |
| 73 | 73 |
return trustKey, nil |
| 74 | 74 |
} |
| ... | ... |
@@ -9,6 +9,7 @@ import ( |
| 9 | 9 |
"net/http/httptest" |
| 10 | 10 |
"os" |
| 11 | 11 |
"path" |
| 12 |
+ "path/filepath" |
|
| 12 | 13 |
"strings" |
| 13 | 14 |
"testing" |
| 14 | 15 |
"time" |
| ... | ... |
@@ -187,6 +188,7 @@ func newTestEngine(t Fataler, autorestart bool, root string) *engine.Engine {
|
| 187 | 187 |
// Either InterContainerCommunication or EnableIptables must be set, |
| 188 | 188 |
// otherwise NewDaemon will fail because of conflicting settings. |
| 189 | 189 |
InterContainerCommunication: true, |
| 190 |
+ TrustKeyPath: filepath.Join(root, "key.json"), |
|
| 190 | 191 |
} |
| 191 | 192 |
d, err := daemon.NewDaemon(cfg, eng) |
| 192 | 193 |
if err != nil {
|
| ... | ... |
@@ -51,7 +51,7 @@ clone hg code.google.com/p/go.net 84a4013f96e0 |
| 51 | 51 |
|
| 52 | 52 |
clone hg code.google.com/p/gosqlite 74691fb6f837 |
| 53 | 53 |
|
| 54 |
-clone git github.com/docker/libtrust d273ef2565ca |
|
| 54 |
+clone git github.com/docker/libtrust 230dfd18c232 |
|
| 55 | 55 |
|
| 56 | 56 |
clone git github.com/Sirupsen/logrus v0.6.0 |
| 57 | 57 |
|
| ... | ... |
@@ -55,16 +55,7 @@ func (k *ecPublicKey) CurveName() string {
|
| 55 | 55 |
|
| 56 | 56 |
// KeyID returns a distinct identifier which is unique to this Public Key. |
| 57 | 57 |
func (k *ecPublicKey) KeyID() string {
|
| 58 |
- // Generate and return a libtrust fingerprint of the EC public key. |
|
| 59 |
- // For an EC key this should be: |
|
| 60 |
- // SHA256("EC"+curveName+bytes(X)+bytes(Y))
|
|
| 61 |
- // Then truncated to 240 bits and encoded into 12 base32 groups like so: |
|
| 62 |
- // ABCD:EFGH:IJKL:MNOP:QRST:UVWX:YZ23:4567:ABCD:EFGH:IJKL:MNOP |
|
| 63 |
- hasher := crypto.SHA256.New() |
|
| 64 |
- hasher.Write([]byte(k.KeyType() + k.CurveName())) |
|
| 65 |
- hasher.Write(k.X.Bytes()) |
|
| 66 |
- hasher.Write(k.Y.Bytes()) |
|
| 67 |
- return keyIDEncode(hasher.Sum(nil)[:30]) |
|
| 58 |
+ return keyIDFromCryptoKey(k) |
|
| 68 | 59 |
} |
| 69 | 60 |
|
| 70 | 61 |
func (k *ecPublicKey) String() string {
|
| ... | ... |
@@ -11,9 +11,21 @@ func FilterByHosts(keys []PublicKey, host string, includeEmpty bool) ([]PublicKe |
| 11 | 11 |
filtered := make([]PublicKey, 0, len(keys)) |
| 12 | 12 |
|
| 13 | 13 |
for _, pubKey := range keys {
|
| 14 |
- hosts, ok := pubKey.GetExtendedField("hosts").([]interface{})
|
|
| 14 |
+ var hosts []string |
|
| 15 |
+ switch v := pubKey.GetExtendedField("hosts").(type) {
|
|
| 16 |
+ case []string: |
|
| 17 |
+ hosts = v |
|
| 18 |
+ case []interface{}:
|
|
| 19 |
+ for _, value := range v {
|
|
| 20 |
+ h, ok := value.(string) |
|
| 21 |
+ if !ok {
|
|
| 22 |
+ continue |
|
| 23 |
+ } |
|
| 24 |
+ hosts = append(hosts, h) |
|
| 25 |
+ } |
|
| 26 |
+ } |
|
| 15 | 27 |
|
| 16 |
- if !ok || (ok && len(hosts) == 0) {
|
|
| 28 |
+ if len(hosts) == 0 {
|
|
| 17 | 29 |
if includeEmpty {
|
| 18 | 30 |
filtered = append(filtered, pubKey) |
| 19 | 31 |
} |
| ... | ... |
@@ -21,12 +33,7 @@ func FilterByHosts(keys []PublicKey, host string, includeEmpty bool) ([]PublicKe |
| 21 | 21 |
} |
| 22 | 22 |
|
| 23 | 23 |
// Check if any hosts match pattern |
| 24 |
- for _, hostVal := range hosts {
|
|
| 25 |
- hostPattern, ok := hostVal.(string) |
|
| 26 |
- if !ok {
|
|
| 27 |
- continue |
|
| 28 |
- } |
|
| 29 |
- |
|
| 24 |
+ for _, hostPattern := range hosts {
|
|
| 30 | 25 |
match, err := filepath.Match(hostPattern, host) |
| 31 | 26 |
if err != nil {
|
| 32 | 27 |
return nil, err |
| ... | ... |
@@ -37,7 +44,6 @@ func FilterByHosts(keys []PublicKey, host string, includeEmpty bool) ([]PublicKe |
| 37 | 37 |
continue |
| 38 | 38 |
} |
| 39 | 39 |
} |
| 40 |
- |
|
| 41 | 40 |
} |
| 42 | 41 |
|
| 43 | 42 |
return filtered, nil |
| ... | ... |
@@ -27,6 +27,8 @@ func TestFilter(t *testing.T) {
|
| 27 | 27 |
t.Fatal(err) |
| 28 | 28 |
} |
| 29 | 29 |
|
| 30 |
+ // we use both []interface{} and []string here because jwt uses
|
|
| 31 |
+ // []interface{} format, while PEM uses []string
|
|
| 30 | 32 |
switch {
|
| 31 | 33 |
case i == 0: |
| 32 | 34 |
// Don't add entries for this key, key 0. |
| ... | ... |
@@ -36,10 +38,10 @@ func TestFilter(t *testing.T) {
|
| 36 | 36 |
key.AddExtendedField("hosts", []interface{}{"*.even.example.com"})
|
| 37 | 37 |
case i == 7: |
| 38 | 38 |
// Should catch only the last key, and make it match any hostname. |
| 39 |
- key.AddExtendedField("hosts", []interface{}{"*"})
|
|
| 39 |
+ key.AddExtendedField("hosts", []string{"*"})
|
|
| 40 | 40 |
default: |
| 41 | 41 |
// should catch keys 1, 3, 5. |
| 42 |
- key.AddExtendedField("hosts", []interface{}{"*.example.com"})
|
|
| 42 |
+ key.AddExtendedField("hosts", []string{"*.example.com"})
|
|
| 43 | 43 |
} |
| 44 | 44 |
|
| 45 | 45 |
keys = append(keys, key) |
| ... | ... |
@@ -138,7 +138,7 @@ func testTrustedHostKeysFile(t *testing.T, trustedHostKeysFilename string) {
|
| 138 | 138 |
} |
| 139 | 139 |
|
| 140 | 140 |
for addr, hostKey := range trustedHostKeysMapping {
|
| 141 |
- t.Logf("Host Address: %s\n", addr)
|
|
| 141 |
+ t.Logf("Host Address: %d\n", addr)
|
|
| 142 | 142 |
t.Logf("Host Key: %s\n\n", hostKey)
|
| 143 | 143 |
} |
| 144 | 144 |
|
| ... | ... |
@@ -160,7 +160,7 @@ func testTrustedHostKeysFile(t *testing.T, trustedHostKeysFilename string) {
|
| 160 | 160 |
} |
| 161 | 161 |
|
| 162 | 162 |
for addr, hostKey := range trustedHostKeysMapping {
|
| 163 |
- t.Logf("Host Address: %s\n", addr)
|
|
| 163 |
+ t.Logf("Host Address: %d\n", addr)
|
|
| 164 | 164 |
t.Logf("Host Key: %s\n\n", hostKey)
|
| 165 | 165 |
} |
| 166 | 166 |
|
| ... | ... |
@@ -34,16 +34,7 @@ func (k *rsaPublicKey) KeyType() string {
|
| 34 | 34 |
|
| 35 | 35 |
// KeyID returns a distinct identifier which is unique to this Public Key. |
| 36 | 36 |
func (k *rsaPublicKey) KeyID() string {
|
| 37 |
- // Generate and return a 'libtrust' fingerprint of the RSA public key. |
|
| 38 |
- // For an RSA key this should be: |
|
| 39 |
- // SHA256("RSA"+bytes(N)+bytes(E))
|
|
| 40 |
- // Then truncated to 240 bits and encoded into 12 base32 groups like so: |
|
| 41 |
- // ABCD:EFGH:IJKL:MNOP:QRST:UVWX:YZ23:4567:ABCD:EFGH:IJKL:MNOP |
|
| 42 |
- hasher := crypto.SHA256.New() |
|
| 43 |
- hasher.Write([]byte(k.KeyType())) |
|
| 44 |
- hasher.Write(k.N.Bytes()) |
|
| 45 |
- hasher.Write(serializeRSAPublicExponentParam(k.E)) |
|
| 46 |
- return keyIDEncode(hasher.Sum(nil)[:30]) |
|
| 37 |
+ return keyIDFromCryptoKey(k) |
|
| 47 | 38 |
} |
| 48 | 39 |
|
| 49 | 40 |
func (k *rsaPublicKey) String() string {
|
| ... | ... |
@@ -201,7 +201,7 @@ func TestCollapseGrants(t *testing.T) {
|
| 201 | 201 |
|
| 202 | 202 |
collapsedGrants, expiration, err := CollapseStatements(statements, false) |
| 203 | 203 |
if len(collapsedGrants) != 12 {
|
| 204 |
- t.Fatalf("Unexpected number of grants\n\tExpected: %d\n\tActual: %s", 12, len(collapsedGrants))
|
|
| 204 |
+ t.Fatalf("Unexpected number of grants\n\tExpected: %d\n\tActual: %d", 12, len(collapsedGrants))
|
|
| 205 | 205 |
} |
| 206 | 206 |
if expiration.After(time.Now().Add(time.Hour*5)) || expiration.Before(time.Now()) {
|
| 207 | 207 |
t.Fatalf("Unexpected expiration time: %s", expiration.String())
|
| ... | ... |
@@ -261,7 +261,7 @@ func TestCollapseGrants(t *testing.T) {
|
| 261 | 261 |
|
| 262 | 262 |
collapsedGrants, expiration, err = CollapseStatements(statements, false) |
| 263 | 263 |
if len(collapsedGrants) != 12 {
|
| 264 |
- t.Fatalf("Unexpected number of grants\n\tExpected: %d\n\tActual: %s", 12, len(collapsedGrants))
|
|
| 264 |
+ t.Fatalf("Unexpected number of grants\n\tExpected: %d\n\tActual: %d", 12, len(collapsedGrants))
|
|
| 265 | 265 |
} |
| 266 | 266 |
if expiration.After(time.Now().Add(time.Hour*5)) || expiration.Before(time.Now()) {
|
| 267 | 267 |
t.Fatalf("Unexpected expiration time: %s", expiration.String())
|
| ... | ... |
@@ -2,6 +2,7 @@ package libtrust |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"bytes" |
| 5 |
+ "crypto" |
|
| 5 | 6 |
"crypto/elliptic" |
| 6 | 7 |
"crypto/x509" |
| 7 | 8 |
"encoding/base32" |
| ... | ... |
@@ -52,6 +53,21 @@ func keyIDEncode(b []byte) string {
|
| 52 | 52 |
return buf.String() |
| 53 | 53 |
} |
| 54 | 54 |
|
| 55 |
+func keyIDFromCryptoKey(pubKey PublicKey) string {
|
|
| 56 |
+ // Generate and return a 'libtrust' fingerprint of the public key. |
|
| 57 |
+ // For an RSA key this should be: |
|
| 58 |
+ // SHA256(DER encoded ASN1) |
|
| 59 |
+ // Then truncated to 240 bits and encoded into 12 base32 groups like so: |
|
| 60 |
+ // ABCD:EFGH:IJKL:MNOP:QRST:UVWX:YZ23:4567:ABCD:EFGH:IJKL:MNOP |
|
| 61 |
+ derBytes, err := x509.MarshalPKIXPublicKey(pubKey.CryptoPublicKey()) |
|
| 62 |
+ if err != nil {
|
|
| 63 |
+ return "" |
|
| 64 |
+ } |
|
| 65 |
+ hasher := crypto.SHA256.New() |
|
| 66 |
+ hasher.Write(derBytes) |
|
| 67 |
+ return keyIDEncode(hasher.Sum(nil)[:30]) |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 55 | 70 |
func stringFromMap(m map[string]interface{}, key string) (string, error) {
|
| 56 | 71 |
val, ok := m[key] |
| 57 | 72 |
if !ok {
|
| 58 | 73 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,23 @@ |
| 0 |
+package libtrust |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/pem" |
|
| 4 |
+ "reflect" |
|
| 5 |
+ "testing" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+func TestAddPEMHeadersToKey(t *testing.T) {
|
|
| 9 |
+ pk := &rsaPublicKey{nil, map[string]interface{}{}}
|
|
| 10 |
+ blk := &pem.Block{Headers: map[string]string{"hosts": "localhost,127.0.0.1"}}
|
|
| 11 |
+ addPEMHeadersToKey(blk, pk) |
|
| 12 |
+ |
|
| 13 |
+ val := pk.GetExtendedField("hosts")
|
|
| 14 |
+ hosts, ok := val.([]string) |
|
| 15 |
+ if !ok {
|
|
| 16 |
+ t.Fatalf("hosts type(%v), expected []string", reflect.TypeOf(val))
|
|
| 17 |
+ } |
|
| 18 |
+ expected := []string{"localhost", "127.0.0.1"}
|
|
| 19 |
+ if !reflect.DeepEqual(hosts, expected) {
|
|
| 20 |
+ t.Errorf("hosts(%v), expected %v", hosts, expected)
|
|
| 21 |
+ } |
|
| 22 |
+} |