func TestRenewLease(t *testing.T) { msr := newDummyRegistry() sm := NewMockManager(msr) now := time.Now() fakeClock := clockwork.NewFakeClockAt(now) clock = fakeClock // Create LeaseAttrs extIaddr, _ := ip.ParseIP4("1.2.3.4") attrs := LeaseAttrs{ PublicIP: extIaddr, BackendType: "vxlan", } ld, err := json.Marshal(&leaseData{Dummy: "test string"}) if err != nil { t.Fatalf("Failed to marshal leaseData: %v", err) } attrs.BackendData = json.RawMessage(ld) // Acquire lease ctx, cancel := context.WithCancel(context.Background()) defer cancel() l, err := sm.AcquireLease(ctx, "_", &attrs) if err != nil { t.Fatal("AcquireLease failed: ", err) } now = now.Add(subnetTTL) fakeClock.Advance(24 * time.Hour) if err := sm.RenewLease(ctx, "_", l); err != nil { t.Fatal("RenewLease failed: ", err) } // check that it's still good n, err := msr.getNetwork(ctx, "_") if err != nil { t.Error("Failed to renew lease: could not get networks: %v", err) } for _, sn := range n.subnets { if sn.Subnet.Equal(l.Subnet) { expected := now.Add(subnetTTL) if !sn.Expiration.Equal(expected) { t.Errorf("Failed to renew lease: bad expiration; expected %v, got %v", expected, sn.Expiration) } if !reflect.DeepEqual(sn.Attrs, attrs) { t.Errorf("LeaseAttrs changed: was %#v, now %#v", attrs, sn.Attrs) } return } } t.Fatalf("Failed to find acquired lease") }
func init() { twilio.Clock = clockwork.NewFakeClockAt(time.Unix(1257894000, 0)) }
func TestTrackRemoteThenLocalTemp(t *testing.T) { tc := SetupEngineTest(t, "track") defer tc.Cleanup() fu := CreateAndSignupFakeUser(tc, "track") // Tracking remote means we have to agree what time it is fakeClock := clockwork.NewFakeClockAt(time.Now()) tc.G.SetClock(fakeClock) // to pick up the new clock... tc.G.ResetLoginState() flakeyAPI := flakeyRooterAPI{orig: tc.G.XAPI, flakeOut: false, G: tc.G} tc.G.XAPI = &flakeyAPI idUI := &FakeIdentifyUI{} username := "******" arg := &keybase1.Identify2Arg{ UserAssertion: username, NeedProofSet: true, } ctx := &Context{ LogUI: tc.G.UI.GetLogUI(), IdentifyUI: idUI, SecretUI: fu.NewSecretUI(), } // Identify tracy; all proofs should work eng := NewResolveThenIdentify2(tc.G, arg) if err := RunEngine(eng, ctx); err != nil { t.Fatal(err) } // Leaving LocalOnly off here will result in remote tracking targ := TrackTokenArg{ Token: idUI.Token, Options: keybase1.TrackOptions{BypassConfirm: true}, } // Track tracy teng := NewTrackToken(&targ, tc.G) if err := RunEngine(teng, ctx); err != nil { t.Fatal(err) } defer runUntrack(tc.G, fu, username) // Now make her Rooter proof fail with a 429 flakeyAPI.flakeOut = true idUI = &FakeIdentifyUI{} ctx.IdentifyUI = idUI // Advance so that our previous cached success is out of // cache fakeClock.Advance(tc.G.Env.GetProofCacheLongDur() + time.Minute) eng = NewResolveThenIdentify2(tc.G, arg) eng.testArgs = &Identify2WithUIDTestArgs{noCache: true} // Should get an error if err := RunEngine(eng, ctx); err == nil { t.Fatal("Expected identify error") } result, found := idUI.ProofResults["rooter"] if !found { t.Fatal("Failed to find a rooter proof") } if pe := libkb.ImportProofError(result.ProofResult); pe == nil { t.Fatal("expected a Rooter error result") } // This is like the UI saying to store the local track targ.Options.ExpiringLocal = true targ.Token = idUI.Token // Track tracy teng = NewTrackToken(&targ, tc.G) if err := RunEngine(teng, ctx); err != nil { t.Fatal(err) } // Identify should work once more because we signed with failures eng = NewResolveThenIdentify2(tc.G, arg) eng.testArgs = &Identify2WithUIDTestArgs{noCache: true} var err error // Should not get an error if err = RunEngine(eng, ctx); err != nil { t.Logf("Identify failure: %v", err) t.Fatal("Expected to pass identify") } result, found = idUI.ProofResults["rooter"] if !found { t.Fatal("Failed to find a rooter proof") } if pe := libkb.ImportProofError(result.ProofResult); pe == nil { t.Fatal("expected a Rooter error result") } // Advance so that our temporary track is discarded // cache fakeClock.Advance(tc.G.Env.GetLocalTrackMaxAge() + time.Minute) // Identify should fail once more eng = NewResolveThenIdentify2(tc.G, arg) eng.testArgs = &Identify2WithUIDTestArgs{noCache: true} // Should get an error if err = RunEngine(eng, ctx); err == nil { t.Fatal("Expected rooter to fail") } t.Logf("Identify failure: %v", err) result, found = idUI.ProofResults["rooter"] if !found { t.Fatal("Failed to find a rooter proof") } if pe := libkb.ImportProofError(result.ProofResult); pe == nil { t.Fatal("expected a Rooter error result") } assertTracking(tc, username) }
func TestMigrate(t *testing.T) { dir, err := ioutil.TempDir("", tstprefix) if err != nil { t.Fatalf("error creating tempdir: %v", err) } defer os.RemoveAll(dir) blobKeys := []string{ "sha512-aaaaaaaa", "sha512-bbbbbbbb", } names := []string{ "example.com/app01", "example.com/app02", } sizes := []int64{ 0, 2 << 8, } treeStoreSizes := []int64{ 0, 2 << 8, 2 << 16, } insecureOptions := []int64{ 0, 2, } now := time.Now().UTC() // Injects a fake clock to store pkg clock clock = clockwork.NewFakeClockAt(now) tests := []migrateTest{ { // Test migration from V0 to V1 with an empty database &DBV0{}, &DBV1{}, &DBV1{}, }, { // Test migration from V0 to V1 &DBV0{ []*ACIInfoV0_2{ {blobKeys[0], names[0], now, false}, {blobKeys[1], names[1], now, true}, }, []*RemoteV0_1{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0]}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1]}, }, }, &DBV1{ []*ACIInfoV0_2{ {blobKeys[0], names[0], now, false}, {blobKeys[1], names[1], now, true}, }, []*RemoteV0_1{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0]}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1]}, }, }, &DBV1{}, }, { // Test migration from V1 to V2 &DBV1{ []*ACIInfoV0_2{ {blobKeys[0], "example.com/app01", now, false}, {blobKeys[1], "example.com/app02", now, true}, }, []*RemoteV0_1{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0]}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1]}, }, }, &DBV2{ []*ACIInfoV0_2{ {blobKeys[0], "example.com/app01", now, false}, {blobKeys[1], "example.com/app02", now, true}, }, []*RemoteV2_7{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0], 0, time.Time{}.UTC()}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1], 0, time.Time{}.UTC()}, }, }, &DBV2{}, }, { // Test migration from V2 to V3 &DBV2{ []*ACIInfoV0_2{ {blobKeys[0], "example.com/app01", now, false}, {blobKeys[1], "example.com/app02", now, true}, }, []*RemoteV2_7{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0], 0, time.Time{}.UTC()}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1], 0, time.Time{}.UTC()}, }, }, &DBV3{ []*ACIInfoV3{ {blobKeys[0], "example.com/app01", now, false}, {blobKeys[1], "example.com/app02", now, true}, }, []*RemoteV2_7{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0], 0, time.Time{}.UTC()}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1], 0, time.Time{}.UTC()}, }, }, &DBV3{}, }, { // Test migration from V3 to V4 &DBV3{ []*ACIInfoV3{ {BlobKey: blobKeys[0], Name: names[0], ImportTime: now, Latest: false}, {BlobKey: blobKeys[1], Name: names[1], ImportTime: now, Latest: true}, }, []*RemoteV2_7{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0], 0, time.Time{}.UTC()}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1], 0, time.Time{}.UTC()}, }, }, &DBV4{ []*ACIInfoV4{ {BlobKey: blobKeys[0], Name: names[0], ImportTime: now, LastUsed: now, Latest: false}, {BlobKey: blobKeys[1], Name: names[1], ImportTime: now, LastUsed: now, Latest: true}, }, []*RemoteV2_7{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0], 0, time.Time{}.UTC()}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1], 0, time.Time{}.UTC()}, }, }, &DBV4{}, }, { // Test migration from V4 to V5 &DBV4{ []*ACIInfoV4{ {BlobKey: blobKeys[0], Name: names[0], ImportTime: now, LastUsed: now, Latest: false}, {BlobKey: blobKeys[1], Name: names[1], ImportTime: now, LastUsed: now, Latest: true}, }, []*RemoteV2_7{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0], 0, time.Time{}.UTC()}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1], 0, time.Time{}.UTC()}, }, }, &DBV5{ []*ACIInfoV5{ {BlobKey: blobKeys[0], Name: names[0], ImportTime: now, LastUsed: now, Latest: false}, {BlobKey: blobKeys[1], Name: names[1], ImportTime: now, LastUsed: now, Latest: true}, }, []*RemoteV2_7{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0], 0, time.Time{}.UTC()}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1], 0, time.Time{}.UTC()}, }, }, &DBV5{}, }, { // Test migration from V5 to V6 &DBV5{ []*ACIInfoV5{ {BlobKey: blobKeys[0], Name: names[0], ImportTime: now, LastUsed: now, Latest: false, Size: sizes[0], TreeStoreSize: treeStoreSizes[0]}, {BlobKey: blobKeys[1], Name: names[1], ImportTime: now, LastUsed: now, Latest: true, Size: sizes[1], TreeStoreSize: treeStoreSizes[1]}, }, []*RemoteV2_7{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0], 0, time.Time{}.UTC()}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1], 0, time.Time{}.UTC()}, }, }, &DBV6{ []*ACIInfoV6{ {BlobKey: blobKeys[0], Name: names[0], ImportTime: now, LastUsed: now, Latest: false, Size: sizes[0], TreeStoreSize: treeStoreSizes[0]}, {BlobKey: blobKeys[1], Name: names[1], ImportTime: now, LastUsed: now, Latest: true, Size: sizes[1], TreeStoreSize: treeStoreSizes[1]}, }, []*RemoteV2_7{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0], 0, time.Time{}.UTC()}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1], 0, time.Time{}.UTC()}, }, }, &DBV6{}, }, { // Test migration from V6 to V7 &DBV6{ []*ACIInfoV6{ {BlobKey: blobKeys[0], Name: names[0], ImportTime: now, LastUsed: now, Latest: false, Size: sizes[0], TreeStoreSize: treeStoreSizes[0], InsecureOptions: insecureOptions[0]}, {BlobKey: blobKeys[1], Name: names[1], ImportTime: now, LastUsed: now, Latest: true, Size: sizes[1], TreeStoreSize: treeStoreSizes[1], InsecureOptions: insecureOptions[1]}, }, []*RemoteV2_7{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0], 0, time.Time{}.UTC()}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1], 0, time.Time{}.UTC()}, }, }, &DBV7{ []*ACIInfoV7{ {BlobKey: blobKeys[0], Name: names[0], ImportTime: now, LastUsed: now, Latest: false, Size: sizes[0], TreeStoreSize: treeStoreSizes[0]}, {BlobKey: blobKeys[1], Name: names[1], ImportTime: now, LastUsed: now, Latest: true, Size: sizes[1], TreeStoreSize: treeStoreSizes[1]}, }, []*RemoteV2_7{ {"http://example.com/app01.aci", "http://example.com/app01.aci.asc", "", blobKeys[0], 0, time.Time{}.UTC()}, {"http://example.com/app02.aci", "http://example.com/app02.aci.asc", "", blobKeys[1], 0, time.Time{}.UTC()}, }, }, &DBV7{}, }, } for i, tt := range tests { if err := testMigrate(tt); err != nil { t.Errorf("#%d: unexpected error: %v", i, err) } } }
func TestSoftSnooze(t *testing.T) { tc := SetupEngineTest(t, "track") defer tc.Cleanup() fu := CreateAndSignupFakeUser(tc, "track") fakeClock := clockwork.NewFakeClockAt(time.Now()) tc.G.SetClock(fakeClock) // to pick up the new clock... tc.G.ResetLoginState() flakeyAPI := flakeyRooterAPI{orig: tc.G.XAPI, flakeOut: false, G: tc.G} tc.G.XAPI = &flakeyAPI idUI := &FakeIdentifyUI{} username := "******" arg := &keybase1.Identify2Arg{ UserAssertion: username, NeedProofSet: true, } ctx := &Context{ LogUI: tc.G.UI.GetLogUI(), IdentifyUI: idUI, SecretUI: fu.NewSecretUI(), } // Identify tracy; all proofs should work eng := NewResolveThenIdentify2(tc.G, arg) if err := RunEngine(eng, ctx); err != nil { t.Fatal(err) } targ := TrackTokenArg{ Token: idUI.Token, Options: keybase1.TrackOptions{BypassConfirm: true}, } // Track tracy teng := NewTrackToken(&targ, tc.G) if err := RunEngine(teng, ctx); err != nil { t.Fatal(err) } defer runUntrack(tc.G, fu, username) // Now make her Rooter proof flakey / fail with a 429 flakeyAPI.flakeOut = true idUI = &FakeIdentifyUI{} ctx.IdentifyUI = idUI // Advance so that our previous cached success is out of // cache on its own, but still can override a 429-like soft failure. fakeClock.Advance(tc.G.Env.GetProofCacheMediumDur() + time.Minute) eng = NewResolveThenIdentify2(tc.G, arg) eng.testArgs = &Identify2WithUIDTestArgs{noCache: true} // Should not get an error if err := RunEngine(eng, ctx); err != nil { t.Fatal(err) } result, found := idUI.ProofResults["rooter"] if !found { t.Fatal("Failed to find a rooter proof") } if pe := libkb.ImportProofError(result.SnoozedResult); pe == nil { t.Fatal("expected a snoozed error result") } // Now time out the success that allowed us to circumvent // the soft failure. fakeClock.Advance(tc.G.Env.GetProofCacheLongDur()) eng = NewResolveThenIdentify2(tc.G, arg) eng.testArgs = &Identify2WithUIDTestArgs{noCache: true} idUI = &FakeIdentifyUI{} ctx.IdentifyUI = idUI if err := RunEngine(eng, ctx); err == nil { t.Fatal("Expected a failure in our proof") } result, found = idUI.ProofResults["rooter"] if !found { t.Fatal("Failed to find a rooter proof") } if pe := libkb.ImportProofError(result.ProofResult); pe == nil { t.Fatal("expected a Rooter error result") } if !idUI.BrokenTracking { t.Fatal("expected broken tracking!") } assertTracking(tc, username) }