The token carries the node's name
Found by raising a mesh end to end. The broker account a joining node authenticates as is named after the node, and exists before that machine has been told anything — so the node has to know its name before the mesh can tell it. Without it, enrolment fails at the broker with an empty username, which says nothing about why. Not a secret, and the issuer already knows it. The wire-format test now covers it, so a rename on either side fails in both repositories rather than at enrolment on a real machine.
This commit is contained in:
@@ -14,6 +14,7 @@ func complete(t *testing.T) Token {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return Token{
|
||||
Node: "anchor",
|
||||
Broker: "192.0.2.10:5671",
|
||||
Fingerprint: "sha256:" + strings.Repeat("ab", 32),
|
||||
Signer: public,
|
||||
@@ -85,8 +86,8 @@ func TestEveryMissingPartIsNamed(t *testing.T) {
|
||||
// decision into four.
|
||||
empty := Token{}
|
||||
missing := empty.Missing()
|
||||
if len(missing) != 4 {
|
||||
t.Fatalf("an empty token named %d missing parts, expected 4: %v", len(missing), missing)
|
||||
if len(missing) != 5 {
|
||||
t.Fatalf("an empty token named %d missing parts, expected 5: %v", len(missing), missing)
|
||||
}
|
||||
if empty.Complete() {
|
||||
t.Error("an empty token reported itself complete")
|
||||
@@ -105,7 +106,7 @@ func TestAShortSigningKeyIsNotASigningKey(t *testing.T) {
|
||||
|
||||
func TestACompleteTokenIsComplete(t *testing.T) {
|
||||
if got := complete(t); !got.Complete() {
|
||||
t.Errorf("a token with all four parts reported missing: %v", got.Missing())
|
||||
t.Errorf("a token with every part reported missing: %v", got.Missing())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,12 +132,27 @@ func TestTheWireFormatIsExactlyTheseFieldNames(t *testing.T) {
|
||||
if err := json.Unmarshal(raw, &fields); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, want := range []string{"v", "broker", "fingerprint", "signer", "secret"} {
|
||||
for _, want := range []string{"v", "node", "broker", "fingerprint", "signer", "secret"} {
|
||||
if _, ok := fields[want]; !ok {
|
||||
t.Errorf("the token has no %q field; the host reads that name", want)
|
||||
}
|
||||
}
|
||||
if len(fields) != 5 {
|
||||
t.Errorf("the token has %d fields, expected 5: %v", len(fields), fields)
|
||||
if len(fields) != 6 {
|
||||
t.Errorf("the token has %d fields, expected 6: %v", len(fields), fields)
|
||||
}
|
||||
}
|
||||
|
||||
func TestATokenWithNoNameIsRefused(t *testing.T) {
|
||||
// The broker account a joining node authenticates as is named after the node, so the node has
|
||||
// to know its name before the mesh can tell it anything. Without this the connection is
|
||||
// refused with an empty username, which says nothing about the cause — which is exactly how
|
||||
// it went the first time a mesh was raised end to end.
|
||||
without := complete(t)
|
||||
without.Node = ""
|
||||
if without.Complete() {
|
||||
t.Fatal("a token with no node name reported itself usable")
|
||||
}
|
||||
if !strings.Contains(strings.Join(without.Missing(), " "), "node's name") {
|
||||
t.Fatalf("the refusal does not say what is missing: %v", without.Missing())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user