Skip to content

Commit 6aec264

Browse files
committed
A number of changes:
* Updating PyYAML, Jinja2 and Fleetspeak dependencies. * Artifacts work.
1 parent 6567156 commit 6aec264

25 files changed

+816
-185
lines changed

grr/client_builder/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def make_release_tree(self, base_dir, files):
7171
"grr-response-client==%s" % VERSION.get("Version", "packagedepends"),
7272
"grr-response-core==%s" % VERSION.get("Version", "packagedepends"),
7373
"PyInstaller==3.6",
74-
"fleetspeak-client-bin==0.1.7.4",
74+
"fleetspeak-client-bin==0.1.9",
7575
"olefile==0.46",
7676
],
7777

grr/core/grr_response_core/lib/rdfvalues/artifacts.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,18 @@ def Validate(self):
413413
raise ValueError("No artifacts to collect.")
414414

415415

416+
class ArtifactProgress(rdf_structs.RDFProtoStruct):
417+
"""Collection progress of an Artifact."""
418+
protobuf = flows_pb2.ArtifactProgress
419+
rdf_deps = []
420+
421+
422+
class ArtifactCollectorFlowProgress(rdf_structs.RDFProtoStruct):
423+
"""Collection progress of ArtifactCollectorFlow."""
424+
protobuf = flows_pb2.ArtifactCollectorFlowProgress
425+
rdf_deps = [ArtifactProgress]
426+
427+
416428
class ClientArtifactCollectorArgs(rdf_structs.RDFProtoStruct):
417429
"""An RDFValue representation of an artifact bundle."""
418430
protobuf = artifact_pb2.ClientArtifactCollectorArgs

grr/core/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def make_release_tree(self, base_dir, files):
152152
"python-dateutil==2.8.1",
153153
"pytsk3==20200117",
154154
"pytz==2020.1",
155-
"PyYAML==5.3.1",
155+
"PyYAML==5.4.1",
156156
"requests==2.25.1",
157157
"yara-python==4.0.1",
158158
],

grr/proto/grr_response_proto/flows.proto

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,15 @@ message ArtifactCollectorFlowArgs {
723723
}];
724724
}
725725

726+
message ArtifactProgress {
727+
optional string name = 1;
728+
optional uint32 num_results = 2;
729+
}
730+
731+
message ArtifactCollectorFlowProgress {
732+
repeated ArtifactProgress artifacts = 1;
733+
}
734+
726735
// Next field ID: 11
727736
message ArtifactFilesDownloaderFlowArgs {
728737
repeated string artifact_list = 1 [(sem_type) = {

grr/server/grr_response_server/flows/general/collectors.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class ArtifactCollectorFlow(flow_base.FlowBase):
8888

8989
category = "/Collectors/"
9090
args_type = rdf_artifacts.ArtifactCollectorFlowArgs
91+
progress_type = rdf_artifacts.ArtifactCollectorFlowProgress
9192
behaviours = flow_base.BEHAVIOUR_BASIC
9293

9394
def Start(self):
@@ -98,6 +99,7 @@ def Start(self):
9899
self.state.failed_count = 0
99100
self.state.knowledge_base = self.args.knowledge_base
100101
self.state.response_count = 0
102+
self.state.progress = rdf_artifacts.ArtifactCollectorFlowProgress()
101103

102104
if self.args.use_tsk and self.args.use_raw_filesystem_access:
103105
raise ValueError(
@@ -162,6 +164,9 @@ def Collect(self, artifact_obj):
162164
"""Collect the raw data from the client for this artifact."""
163165
artifact_name = artifact_obj.name
164166

167+
# Ensure attempted artifacts are shown in progress, even with 0 results.
168+
self._GetOrInsertArtifactProgress(artifact_name)
169+
165170
test_conditions = list(artifact_obj.conditions)
166171
os_conditions = ConvertSupportedOSToConditions(artifact_obj)
167172
if os_conditions:
@@ -748,6 +753,10 @@ def _ParseResponses(self, responses, artifact_name, source):
748753
else:
749754
results = responses
750755

756+
# Increment artifact result count in flow progress.
757+
progress = self._GetOrInsertArtifactProgress(artifact_name)
758+
progress.num_results += len(results)
759+
751760
for result in results:
752761
result_type = result.__class__.__name__
753762
if result_type == "Anomaly":
@@ -756,6 +765,18 @@ def _ParseResponses(self, responses, artifact_name, source):
756765
self.state.response_count += 1
757766
self.SendReply(result, tag="artifact:%s" % artifact_name)
758767

768+
def GetProgress(self) -> rdf_artifacts.ArtifactCollectorFlowProgress:
769+
return self.state.progress
770+
771+
def _GetOrInsertArtifactProgress(self,
772+
name: str) -> rdf_artifacts.ArtifactProgress:
773+
try:
774+
return next(a for a in self.state.progress.artifacts if a.name == name)
775+
except StopIteration:
776+
progress = rdf_artifacts.ArtifactProgress(name=name)
777+
self.state.progress.artifacts.append(progress)
778+
return progress
779+
759780
def End(self, responses):
760781
del responses
761782
# If we got no responses, and user asked for it, we error out.

grr/server/grr_response_server/flows/general/collectors_test.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,56 @@ def testParsingFailure(self):
452452
results = flow_test_lib.GetFlowResults(client_id, flow_id)
453453
self.assertEmpty(results)
454454

455+
def testFlowProgressHasEntryForArtifactWithoutResults(self):
456+
457+
client_id = self.SetupClient(0, system="Linux")
458+
with utils.Stubber(psutil, "process_iter", lambda: iter([])):
459+
client_mock = action_mocks.ActionMock(standard.ListProcesses)
460+
461+
self.fakeartifact.sources.append(
462+
rdf_artifacts.ArtifactSource(
463+
type=rdf_artifacts.ArtifactSource.SourceType.GRR_CLIENT_ACTION,
464+
attributes={"client_action": standard.ListProcesses.__name__}))
465+
466+
flow_id = flow_test_lib.TestFlowHelper(
467+
collectors.ArtifactCollectorFlow.__name__,
468+
client_mock,
469+
artifact_list=["FakeArtifact"],
470+
client_id=client_id)
471+
472+
progress = flow_test_lib.GetFlowProgress(client_id, flow_id)
473+
self.assertLen(progress.artifacts, 1)
474+
self.assertEqual(progress.artifacts[0].name, "FakeArtifact")
475+
self.assertEqual(progress.artifacts[0].num_results, 0)
476+
477+
def testFlowProgressIsCountingResults(self):
478+
479+
def _Iter():
480+
return iter([
481+
client_test_lib.MockWindowsProcess(),
482+
client_test_lib.MockWindowsProcess()
483+
])
484+
485+
client_id = self.SetupClient(0, system="Linux")
486+
with utils.Stubber(psutil, "process_iter", _Iter):
487+
client_mock = action_mocks.ActionMock(standard.ListProcesses)
488+
489+
self.fakeartifact.sources.append(
490+
rdf_artifacts.ArtifactSource(
491+
type=rdf_artifacts.ArtifactSource.SourceType.GRR_CLIENT_ACTION,
492+
attributes={"client_action": standard.ListProcesses.__name__}))
493+
494+
flow_id = flow_test_lib.TestFlowHelper(
495+
collectors.ArtifactCollectorFlow.__name__,
496+
client_mock,
497+
artifact_list=["FakeArtifact"],
498+
client_id=client_id)
499+
500+
progress = flow_test_lib.GetFlowProgress(client_id, flow_id)
501+
self.assertLen(progress.artifacts, 1)
502+
self.assertEqual(progress.artifacts[0].name, "FakeArtifact")
503+
self.assertEqual(progress.artifacts[0].num_results, 2)
504+
455505

456506
class RelationalTestArtifactCollectors(ArtifactCollectorsTestMixin,
457507
test_lib.GRRBaseTest):

grr/server/grr_response_server/gui/ui/components/client_page/client_page.ng.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
</div>
2626
</div>
2727

28-
<div class="client-approval mat-elevation-z5">
28+
<div class="client-approval mat-elevation-z5"
29+
[style.display]="(this.showApprovalView$ | async) ? 'block' : 'none'">
2930
<approval></approval>
3031
</div>
3132
</mat-drawer-content>

grr/server/grr_response_server/gui/ui/components/client_page/client_page.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,15 @@ export class ClientPage implements OnInit, AfterViewInit, OnDestroy {
5353

5454
@ViewChild('clientDetailsDrawer') clientDetailsDrawer!: MatDrawer;
5555

56-
@ViewChild(Approval, {read: ElementRef}) approvalViewContainer!: ElementRef;
56+
@ViewChild(Approval, {read: ElementRef}) approvalViewContainer?: ElementRef;
5757

5858
approvalHeight: number = 0;
5959

60+
readonly showApprovalView$ = this.clientPageFacade.approvalsEnabled$;
61+
6062
private readonly resizeObserver = new ResizeObserver(() => {
61-
this.approvalHeight = this.approvalViewContainer.nativeElement.offsetHeight;
63+
this.approvalHeight =
64+
this.approvalViewContainer?.nativeElement.offsetHeight ?? 0;
6265
this.changeDetectorRef.markForCheck();
6366
});
6467

@@ -88,7 +91,9 @@ export class ClientPage implements OnInit, AfterViewInit, OnDestroy {
8891
}
8992

9093
ngAfterViewInit() {
91-
this.resizeObserver.observe(this.approvalViewContainer.nativeElement);
94+
if (this.approvalViewContainer !== undefined) {
95+
this.resizeObserver.observe(this.approvalViewContainer.nativeElement);
96+
}
9297

9398
const urlTokens = this.router.routerState.snapshot.url.split('/');
9499
if (urlTokens[urlTokens.length - 1] === ClientPage.CLIENT_DETAILS_ROUTE) {

grr/server/grr_response_server/gui/ui/components/client_page/client_page_test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,28 @@ describe('ClientPage Component', () => {
161161
tick();
162162
discardPeriodicTasks();
163163
}));
164+
165+
it('shows approval iff approvalsEnabled$', () => {
166+
const fixture = TestBed.createComponent(ClientComponent);
167+
fixture.detectChanges();
168+
169+
clientPageFacade.approvalsEnabledSubject.next(true);
170+
fixture.detectChanges();
171+
172+
expect(fixture.debugElement.query(By.css('.client-approval'))
173+
.styles['display'])
174+
.toEqual('block');
175+
});
176+
177+
it('does not show approval if approvalsEnabled$ is false', () => {
178+
const fixture = TestBed.createComponent(ClientComponent);
179+
fixture.detectChanges();
180+
181+
clientPageFacade.approvalsEnabledSubject.next(false);
182+
fixture.detectChanges();
183+
184+
expect(fixture.debugElement.query(By.css('.client-approval'))
185+
.styles['display'])
186+
.toEqual('none');
187+
});
164188
});

grr/server/grr_response_server/gui/ui/components/flow_details/helpers/module.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {TimestampModule} from '@app/components/timestamp/module';
1313

1414
import {FileResultsTable} from './file_results_table';
1515
import {OsqueryResultsTable} from './osquery_results_table';
16+
import {ResultAccordion} from './result_accordion';
1617

1718

1819
/**
@@ -37,11 +38,13 @@ import {OsqueryResultsTable} from './osquery_results_table';
3738
FileResultsTable,
3839
FileModePipe,
3940
OsqueryResultsTable,
41+
ResultAccordion,
4042
],
4143
exports: [
4244
FileResultsTable,
4345
FileModePipe,
4446
OsqueryResultsTable,
47+
ResultAccordion,
4548
],
4649
})
4750
export class HelpersModule {

0 commit comments

Comments
 (0)