bastion 0.54.0
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Invented SIDs: the domain part is made up and names no real domain.
|
||||
const (
|
||||
testSIDAlice = "S-1-5-21-1000000001-1000000002-1000000003-1101"
|
||||
testSIDBob = "S-1-5-21-1000000001-1000000002-1000000003-1102"
|
||||
)
|
||||
|
||||
// One scan asks each SID once, and the account label (winTokenUser) and the
|
||||
// owner's domain (ownerFactsReader) share the answer.
|
||||
func TestSIDNamesAsksEachSIDOncePerScan(t *testing.T) {
|
||||
var calls int32
|
||||
lookup := func(sid string) (string, string, error) {
|
||||
atomic.AddInt32(&calls, 1)
|
||||
switch sid {
|
||||
case testSIDAlice:
|
||||
return "alice", "EXAMPLECORP", nil
|
||||
case testSIDBob:
|
||||
return "bob", "EXAMPLECORP", nil
|
||||
}
|
||||
return "", "", errors.New("none mapped")
|
||||
}
|
||||
names := newSIDNames(lookup, time.Second, make(chan struct{}, 1))
|
||||
for i := 0; i < 40; i++ {
|
||||
if got := winAccountLabel(testSIDAlice, names); got != `EXAMPLECORP\alice` {
|
||||
t.Fatalf("label = %q", got)
|
||||
}
|
||||
if got := winAccountDomain(testSIDAlice, names); got != "EXAMPLECORP" {
|
||||
t.Fatalf("domain = %q", got)
|
||||
}
|
||||
winAccountLabel(testSIDBob, names)
|
||||
}
|
||||
if got := winAccountLabel("S-1-5-21-9-9-9-9", names); got != "S-1-5-21-9-9-9-9" {
|
||||
t.Fatalf("an unmapped SID must be shown as itself, got %q", got)
|
||||
}
|
||||
winAccountDomain("S-1-5-21-9-9-9-9", names)
|
||||
if n := atomic.LoadInt32(&calls); n != 3 {
|
||||
t.Fatalf("%d lookups for 3 distinct SIDs in one scan", n)
|
||||
}
|
||||
}
|
||||
|
||||
// A domain controller that does not answer: the first lookup hangs. The scan
|
||||
// must stop waiting at its budget, every later SID must come back unresolved
|
||||
// at once (no second lookup started), the owner's class must read unknown,
|
||||
// and the next scan must not stack a second blocked lookup behind the first.
|
||||
func TestSIDNamesUnreachableDirectoryDegradesWithinBudget(t *testing.T) {
|
||||
release := make(chan struct{})
|
||||
defer close(release)
|
||||
var calls int32
|
||||
lookup := func(sid string) (string, string, error) {
|
||||
atomic.AddInt32(&calls, 1)
|
||||
<-release
|
||||
return "", "", errors.New("released")
|
||||
}
|
||||
slots := make(chan struct{}, 1)
|
||||
const budget = 150 * time.Millisecond
|
||||
|
||||
for scan := 0; scan < 3; scan++ {
|
||||
names := newSIDNames(lookup, budget, slots)
|
||||
start := time.Now()
|
||||
for i := 0; i < 30; i++ {
|
||||
sid := fmt.Sprintf("S-1-5-21-1000000001-1000000002-1000000003-%d", 2000+i)
|
||||
if got := winAccountLabel(sid, names); got != sid {
|
||||
t.Fatalf("scan %d: unresolved SID shown as %q", scan, got)
|
||||
}
|
||||
o := classifyWinOwner(winOwner{SID: sid, Domain: winAccountDomain(sid, names),
|
||||
Computer: "DESKTOP-TEST", Groups: map[string]bool{}, GroupsKnown: true})
|
||||
if o.Class != ownerUnknown {
|
||||
t.Fatalf("scan %d: class %q for an account whose domain could not be read", scan, o.Class)
|
||||
}
|
||||
}
|
||||
if took := time.Since(start); took > budget+time.Second {
|
||||
t.Fatalf("scan %d spent %v on lookups, budget %v", scan, took, budget)
|
||||
}
|
||||
}
|
||||
if n := atomic.LoadInt32(&calls); n != 1 {
|
||||
t.Fatalf("%d lookups started while the first was still blocked", n)
|
||||
}
|
||||
}
|
||||
|
||||
// A slow but answering lookup is used, and only what it took counts against
|
||||
// the budget.
|
||||
func TestSIDNamesSlowLookupWithinBudgetIsUsed(t *testing.T) {
|
||||
lookup := func(sid string) (string, string, error) {
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
return "carol", "EXAMPLECORP", nil
|
||||
}
|
||||
names := newSIDNames(lookup, 2*time.Second, make(chan struct{}, 1))
|
||||
for i := 0; i < 5; i++ {
|
||||
sid := fmt.Sprintf("S-1-5-21-1000000001-1000000002-1000000003-%d", 3000+i)
|
||||
if d := winAccountDomain(sid, names); d != "EXAMPLECORP" {
|
||||
t.Fatalf("lookup %d within budget came back %q", i, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user