Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
169 commits
Select commit Hold shift + click to select a range
96a8e53
Initial commit
daschwanden May 12, 2025
d2f0ffe
First draft of GRR Datastore Spanner schema
daschwanden May 13, 2025
f5dd3c5
Drop in datastore stubs
daschwanden May 14, 2025
8286b9b
Yara table tests passing
daschwanden May 15, 2025
b94a026
Adds blob_keys table
daschwanden May 16, 2025
3ad2f76
Adds Artifacts table
daschwanden May 19, 2025
b0573a9
Adds HashBlobReferences table
daschwanden May 20, 2025
b7e3f4f
Adds SignedBinaries table
daschwanden May 20, 2025
d21378d
Adds SignedCommands table
daschwanden May 20, 2025
5d76dca
Adds ApiAuditEntry table
daschwanden May 21, 2025
67d2a51
EoD 20250528
daschwanden May 28, 2025
4c9113d
Adds PubSub to Database wrapper
daschwanden Jun 1, 2025
fc32e13
Adds PubSub pull
daschwanden Jun 2, 2025
6aff24b
Refactor RequestQueue class
daschwanden Jun 3, 2025
f874977
Adds MessageHandler read/write
daschwanden Jun 5, 2025
9a16496
Adds MessageHandler lease mgmt
daschwanden Jun 5, 2025
20fad7d
Adds Users table
daschwanden Jun 7, 2025
e1d267b
Adds Clients table
daschwanden Jun 8, 2025
c23ebc4
EoD 20250609
daschwanden Jun 9, 2025
de568f5
EoD 20250610
daschwanden Jun 10, 2025
ae87797
EoD 20250611
daschwanden Jun 11, 2025
140488e
EoD 20250612
daschwanden Jun 12, 2025
884ada8
Adds Paths table
daschwanden Jun 13, 2025
5e3b14b
EoD 20250613
daschwanden Jun 13, 2025
f647151
EoD 20250614
daschwanden Jun 14, 2025
e1b33ae
Adds Hunts table
daschwanden Jun 15, 2025
103dc35
EoD 20250615
daschwanden Jun 15, 2025
e416422
EoD 20250615
daschwanden Jun 15, 2025
4a8ef98
EoD 20250615
daschwanden Jun 15, 2025
304064f
Updates CronJobs table tests
daschwanden Jun 16, 2025
e438006
Adds time tests
daschwanden Jun 16, 2025
1f81835
Updates Flows table tests
daschwanden Jun 16, 2025
7112de3
EoD 20250618
daschwanden Jun 18, 2025
25dd618
Updates FlowRequestProcessing and MessageHandler
daschwanden Jun 19, 2025
25d8ee1
Clean up handlers
daschwanden Jun 19, 2025
8971141
Adds Spanner config variables
daschwanden Jun 20, 2025
06632a3
Clean up Spanner config
daschwanden Jun 20, 2025
6ac79c7
Fix user notification encoding
daschwanden Jun 23, 2025
dd5e077
Make repo owner configurable for container image upload
daschwanden Jun 25, 2025
740e4ef
Merge branch 'google:master' into feature/spanner
daschwanden Jul 7, 2025
f8f12bd
Fix testing compose manifest images
daschwanden Jul 7, 2025
9e608ae
Propagate txn_tag
daschwanden Jul 8, 2025
53a36c0
Propagate txn_tag
daschwanden Jul 8, 2025
934ba71
Adds spanner emulator to test env
daschwanden Jul 12, 2025
af901a0
Update build.yml
daschwanden Jul 13, 2025
cc159ba
Update build steps with Spanner Instance creation
daschwanden Jul 14, 2025
09df46d
Fix Spanner Env variable names
daschwanden Jul 14, 2025
bc72cbd
Run database removal with quiet flag
daschwanden Jul 14, 2025
18506fe
Adds PROJECT_ID env var
daschwanden Jul 14, 2025
8233c2b
Creates unique database name
daschwanden Jul 14, 2025
0bc717f
Creates unique database name
daschwanden Jul 14, 2025
ecce62c
Creates unique database name
daschwanden Jul 14, 2025
3bd6006
Reset the test db
daschwanden Jul 14, 2025
b5e4a45
Reset the test db
daschwanden Jul 14, 2025
098cf51
Several cosmetic improvements
daschwanden Jul 18, 2025
4d46101
Adds fixes to pass Spanner tests and installation instructions
daschwanden Aug 27, 2025
2648089
Removes emulator test instructions
daschwanden Aug 27, 2025
6734876
Update grr/server/grr_response_server/databases/spanner.py
daschwanden Nov 11, 2025
bcbb208
Update grr/server/grr_response_server/databases/spanner.py
daschwanden Nov 11, 2025
6fcb253
Update grr/server/grr_response_server/databases/spanner_artifacts.py
daschwanden Nov 11, 2025
d4c6a59
Update grr/server/grr_response_server/databases/spanner_artifacts.py
daschwanden Nov 11, 2025
d04b82c
Update grr/server/grr_response_server/databases/spanner_artifacts.py
daschwanden Nov 11, 2025
5c967a4
Update grr/server/grr_response_server/databases/spanner_yara_test.py
daschwanden Nov 11, 2025
5c5b2dc
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 18, 2025
2611ad8
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 18, 2025
aff64ce
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 18, 2025
ef4c12d
Update grr/server/grr_response_server/databases/spanner_flows.py
daschwanden Nov 18, 2025
1e256bc
Update grr/server/grr_response_server/databases/spanner_flows.py
daschwanden Nov 18, 2025
540ef4d
Update grr/server/grr_response_server/databases/spanner_flows.py
daschwanden Nov 18, 2025
1e45c72
Update grr/server/grr_response_server/databases/spanner_events.py
daschwanden Nov 18, 2025
99e17ff
Update grr/server/grr_response_server/databases/spanner_paths.py
daschwanden Nov 18, 2025
81ee1a7
Update grr/server/grr_response_server/databases/spanner_flows.py
daschwanden Nov 18, 2025
840b849
Update grr/server/grr_response_server/databases/spanner_flows.py
daschwanden Nov 18, 2025
704a5d4
Update grr/server/grr_response_server/databases/spanner_cron_jobs.py
daschwanden Nov 18, 2025
60668c6
Update grr/server/grr_response_server/databases/spanner_flows.py
daschwanden Nov 18, 2025
9cbe6e1
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 18, 2025
b02c6e2
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 18, 2025
d37bd6a
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 18, 2025
743105c
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 18, 2025
ebab5aa
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 18, 2025
c3c0fad
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 18, 2025
8a92ea7
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 18, 2025
6f3efaf
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 18, 2025
03db3b6
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 18, 2025
785168c
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 25, 2025
30a66dd
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 25, 2025
6ad847d
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 25, 2025
731ba1e
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 25, 2025
97b7b1a
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 25, 2025
fc66c22
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 25, 2025
ce13240
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 25, 2025
3dbec74
Update grr/server/grr_response_server/databases/spanner_flows.py
daschwanden Nov 25, 2025
85a8878
Update grr/server/grr_response_server/databases/spanner_utils_test.py
daschwanden Nov 25, 2025
b1d7cbd
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 25, 2025
428cd12
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 25, 2025
21cbfc7
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 25, 2025
e2f5cbb
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Nov 25, 2025
ada8f5f
Update grr/server/grr_response_server/databases/spanner_utils_test.py
daschwanden Nov 25, 2025
71f8705
Update grr/server/grr_response_server/databases/spanner_utils_test.py
daschwanden Nov 25, 2025
f35b1c8
Update grr/server/grr_response_server/databases/spanner_cron_jobs.py
daschwanden Nov 26, 2025
51865aa
Update grr/server/grr_response_server/databases/spanner_cron_jobs.py
daschwanden Nov 26, 2025
b4efb65
Update grr/server/grr_response_server/databases/spanner_flows.py
daschwanden Nov 27, 2025
3d3f7df
Update grr/server/grr_response_server/databases/db_blob_references_te…
daschwanden Dec 4, 2025
bbdff8b
Update grr/server/grr_response_server/databases/spanner_blob_referenc…
daschwanden Dec 4, 2025
8815af2
Update grr/server/grr_response_server/databases/spanner_blob_referenc…
daschwanden Dec 8, 2025
8550c9d
Update grr/server/grr_response_server/databases/spanner_blob_referenc…
daschwanden Dec 8, 2025
09499b5
Update grr/server/grr_response_server/databases/spanner_blob_referenc…
daschwanden Dec 8, 2025
e19ed85
Update grr/server/grr_response_server/databases/spanner_blob_referenc…
daschwanden Dec 8, 2025
b746fd3
Update grr/server/grr_response_server/databases/spanner_artifacts_tes…
daschwanden Dec 8, 2025
a3cfda3
Update grr/server/grr_response_server/databases/spanner_test_lib.py
daschwanden Dec 8, 2025
12021e3
Update grr/server/grr_response_server/databases/spanner_test_lib.py
daschwanden Dec 8, 2025
7a6e7bb
Update grr/server/grr_response_server/databases/spanner_signed_comman…
daschwanden Dec 8, 2025
752deb4
Update grr/server/grr_response_server/databases/spanner_signed_comman…
daschwanden Dec 8, 2025
f8b755d
Update grr/server/grr_response_server/databases/spanner_signed_comman…
daschwanden Dec 8, 2025
62e0825
Update grr/server/grr_response_server/databases/spanner_blob_keys_tes…
daschwanden Dec 8, 2025
60d5bf0
Update grr/server/grr_response_server/databases/spanner_blob_referenc…
daschwanden Dec 8, 2025
646c11c
Update grr/server/grr_response_server/databases/spanner_clients_test.py
daschwanden Dec 8, 2025
4293098
Update grr/server/grr_response_server/databases/spanner_cron_jobs_tes…
daschwanden Dec 8, 2025
b0586f5
Update grr/server/grr_response_server/databases/spanner_time_test.py
daschwanden Dec 8, 2025
0f4fb60
Update grr/server/grr_response_server/databases/spanner_cron_jobs.py
daschwanden Dec 8, 2025
8011d06
Update grr/server/grr_response_server/databases/spanner_cron_jobs.py
daschwanden Dec 8, 2025
11f63c0
Update grr/server/grr_response_server/databases/spanner_cron_jobs.py
daschwanden Dec 8, 2025
d6ba41f
Update grr/server/grr_response_server/databases/spanner_events_test.py
daschwanden Dec 8, 2025
84f19a7
Update grr/server/grr_response_server/databases/spanner_flows_large_t…
daschwanden Dec 8, 2025
a6ef39d
Update grr/server/grr_response_server/databases/spanner_flows_test.py
daschwanden Dec 8, 2025
fe4c478
Update grr/server/grr_response_server/databases/spanner_flows_test.py
daschwanden Dec 8, 2025
487be8d
Update grr/server/grr_response_server/databases/spanner.py
daschwanden Dec 8, 2025
c8d7334
Update grr/server/grr_response_server/databases/spanner_yara.py
daschwanden Dec 8, 2025
70dcdd2
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 8, 2025
8054c7f
Update grr/server/grr_response_server/databases/spanner_users.py
daschwanden Dec 8, 2025
db70413
Update grr/server/grr_response_server/databases/spanner_users.py
daschwanden Dec 8, 2025
f4ec7c4
Update grr/server/grr_response_server/databases/spanner_users_test.py
daschwanden Dec 8, 2025
016490c
Update grr/server/grr_response_server/databases/spanner_blob_referenc…
daschwanden Dec 9, 2025
d98f50b
Update grr/server/grr_response_server/databases/spanner_flows.py
daschwanden Dec 9, 2025
4072bd9
Update grr/server/grr_response_server/databases/spanner_flows.py
daschwanden Dec 9, 2025
78cf38d
Update grr/server/grr_response_server/databases/spanner_hunts_test.py
daschwanden Dec 9, 2025
42b409d
Update grr/server/grr_response_server/databases/spanner_signed_binari…
daschwanden Dec 9, 2025
71ca032
Update grr/server/grr_response_server/databases/spanner_hunts.py
daschwanden Dec 9, 2025
cf6f18b
Update grr/server/grr_response_server/databases/spanner_paths.py
daschwanden Dec 9, 2025
950ae59
Update grr/server/grr_response_server/databases/spanner_paths.py
daschwanden Dec 9, 2025
9ccda4c
Update grr/server/grr_response_server/databases/spanner_users.py
daschwanden Dec 9, 2025
44f4545
Update grr/server/grr_response_server/databases/spanner_paths.py
daschwanden Dec 9, 2025
579aab9
Update grr/server/grr_response_server/databases/spanner_utils_test.py
daschwanden Dec 9, 2025
6ef67bd
Update grr/server/grr_response_server/databases/spanner_utils_test.py
daschwanden Dec 9, 2025
983120a
Update grr/server/grr_response_server/databases/spanner_utils_test.py
daschwanden Dec 9, 2025
e01cec2
Update grr/server/grr_response_server/databases/spanner_utils_test.py
daschwanden Dec 9, 2025
ed6d0b0
Update grr/server/grr_response_server/databases/spanner_utils_test.py
daschwanden Dec 9, 2025
9ecf5b1
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
64859cd
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
3e9a812
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
1b39610
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
a55c9ec
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
ba61ddf
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
a18f044
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
67ace6a
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
798baef
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
89cfdeb
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
87afd04
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
0ce830e
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
79b3dd8
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
b4fff3f
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
7b02e87
Update grr/server/grr_response_server/databases/spanner_utils.py
daschwanden Dec 9, 2025
474ef8b
Update grr/server/grr_response_server/databases/spanner_signed_binari…
daschwanden Dec 9, 2025
41a495d
Update grr/server/grr_response_server/databases/spanner_signed_binari…
daschwanden Dec 9, 2025
28f1e94
Update grr/server/grr_response_server/databases/spanner_paths_test.py
daschwanden Dec 9, 2025
3336ee9
Update grr/server/grr_response_server/databases/spanner_message_handl…
daschwanden Dec 9, 2025
d60235f
Update grr/server/grr_response_server/databases/spanner_hunts.py
daschwanden Dec 9, 2025
b8f498a
Update grr/server/grr_response_server/databases/spanner_flows.py
daschwanden Dec 9, 2025
993eb01
Update grr/server/grr_response_server/databases/spanner_clients.py
daschwanden Dec 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ on: [push, pull_request]
env:
GCS_BUCKET: autobuilds.grr-response.com
GCS_BUCKET_OPENAPI: autobuilds-grr-openapi
DOCKER_REPOSITORY: ghcr.io/google/grr
DOCKER_REPOSITORY: ghcr.io/${{ github.repository_owner }}/grr
#SPANNER_EMULATOR_HOST: localhost:9010
#SPANNER_DATABASE: grr-database
#SPANNER_INSTANCE: grr-instance
#SPANNER_PROJECT_ID: spanner-emulator-project
#PROJECT_ID: spanner-emulator-project
jobs:
test-devenv:
runs-on: ubuntu-22.04
Expand Down Expand Up @@ -44,6 +49,27 @@ jobs:
fi
python3 -m venv --system-site-packages "${HOME}/INSTALL"
travis/install.sh
#- name: 'Install Cloud SDK'
# uses: google-github-actions/setup-gcloud@v2
# with:
# install_components: 'beta,pubsub-emulator,cloud-spanner-emulator'
#- name: 'Start Spanner emulator'
# run: |
# gcloud config configurations create emulator
# gcloud config set auth/disable_credentials true
# gcloud config set project ${{ env.SPANNER_PROJECT_ID }}
# gcloud config set api_endpoint_overrides/spanner http://localhost:9020/
# gcloud emulators spanner start &
# gcloud spanner instances create ${{ env.SPANNER_INSTANCE }} \
# --config=emulator-config --description="Spanner Test Instance" --nodes=1
# sudo apt-get update
# sudo apt install -y protobuf-compiler libprotobuf-dev
# # Verify that we can create the Spanner Instance and Database
# cd grr/server/grr_response_server/databases
# ./spanner_setup.sh
# cd -
# # Remove the Database for a clean test env
# gcloud spanner databases delete ${{ env.SPANNER_DATABASE }} --instance=${{ env.SPANNER_INSTANCE }} --quiet
- name: Test
run: |
source "${HOME}/INSTALL/bin/activate"
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ grr/server/grr_response_server/gui/ui/.angular/
docker_config_files/*.pem
compose.watch.yaml
Dockerfile.client

grr/server/grr_response_server/databases/spanner_grr.pb
spanner-setup.txt
8 changes: 4 additions & 4 deletions compose.testing.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@

services:
grr-admin-ui:
image: ghcr.io/google/grr:testing
image: ghcr.io/google/grr:test

grr-fleetspeak-frontend:
image: ghcr.io/google/grr:testing
image: ghcr.io/google/grr:test

grr-worker:
image: ghcr.io/google/grr:testing
image: ghcr.io/google/grr:test

grr-client:
image: ghcr.io/google/grr:testing
image: ghcr.io/google/grr:test
privileged: true
30 changes: 30 additions & 0 deletions grr/core/grr_response_core/config/data_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,33 @@
"Only used when Blobstore.implementation is GCSBlobStore."
),
)

# Spanner configuration.
config_lib.DEFINE_string(
"Spanner.project",
default=None,
help=(
"GCP Project where the Spanner Instance is located."
),
)
config_lib.DEFINE_string(
"Spanner.instance",
default="grr-instance",
help="The Spanner Instance for GRR.")

config_lib.DEFINE_string(
"Spanner.database",
default="grr-database",
help="The Spanner Database for GRR.")

config_lib.DEFINE_integer(
"Spanner.flow_processing_threads_min",
default=1,
help="The minimum number of flow-processing worker threads.",
)

config_lib.DEFINE_integer(
"Spanner.flow_processing_threads_max",
default=20,
help="The maximum number of flow-processing worker threads.",
)
12 changes: 6 additions & 6 deletions grr/server/grr_response_server/databases/db_cronjob_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def testCronJobLeasing(self):
job = self._CreateCronJob()
self.db.WriteCronJob(job)

current_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(10000)
current_time = rdfvalue.RDFDatetime.Now()
lease_time = rdfvalue.Duration.From(5, rdfvalue.MINUTES)
with test_lib.FakeTime(current_time):
leased = self.db.LeaseCronJobs(lease_time=lease_time)
Expand Down Expand Up @@ -232,7 +232,7 @@ def testCronJobLeasingByID(self):
for j in jobs:
self.db.WriteCronJob(j)

current_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(10000)
current_time = rdfvalue.RDFDatetime.Now()
lease_time = rdfvalue.Duration.From(5, rdfvalue.MINUTES)
with test_lib.FakeTime(current_time):
leased = self.db.LeaseCronJobs(
Expand All @@ -254,7 +254,7 @@ def testCronJobReturning(self):
with self.assertRaises(ValueError):
self.db.ReturnLeasedCronJobs([job])

current_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(10000)
current_time = rdfvalue.RDFDatetime.Now()
with test_lib.FakeTime(current_time):
leased = self.db.LeaseCronJobs(
cronjob_ids=[leased_job.cron_job_id],
Expand All @@ -276,14 +276,14 @@ def testCronJobReturningMultiple(self):
for j in jobs:
self.db.WriteCronJob(j)

current_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(10000)
current_time = rdfvalue.RDFDatetime.Now()
with test_lib.FakeTime(current_time):
leased = self.db.LeaseCronJobs(
lease_time=rdfvalue.Duration.From(5, rdfvalue.MINUTES)
)
self.assertLen(leased, 3)

current_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(10001)
current_time = rdfvalue.RDFDatetime.Now()
with test_lib.FakeTime(current_time):
unleased_jobs = self.db.LeaseCronJobs(
lease_time=rdfvalue.Duration.From(5, rdfvalue.MINUTES)
Expand All @@ -292,7 +292,7 @@ def testCronJobReturningMultiple(self):

self.db.ReturnLeasedCronJobs(leased)

current_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(10002)
current_time = rdfvalue.RDFDatetime.Now()
with test_lib.FakeTime(current_time):
leased = self.db.LeaseCronJobs(
lease_time=rdfvalue.Duration.From(5, rdfvalue.MINUTES)
Expand Down
17 changes: 9 additions & 8 deletions grr/server/grr_response_server/databases/db_flows_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2270,15 +2270,16 @@ def testWritesAndReadsSingleFlowResultOfSingleType(self):
sample_result = flows_pb2.FlowResult(client_id=client_id, flow_id=flow_id)
sample_result.payload.Pack(jobs_pb2.ClientSummary(client_id=client_id))

with test_lib.FakeTime(42):
current_time = rdfvalue.RDFDatetime.Now()
with test_lib.FakeTime(current_time):
self.db.WriteFlowResults([sample_result])

results = self.db.ReadFlowResults(client_id, flow_id, 0, 100)
self.assertLen(results, 1)
self.assertEqual(results[0].payload, sample_result.payload)
self.assertEqual(
rdfvalue.RDFDatetime.FromMicrosecondsSinceEpoch(results[0].timestamp),
rdfvalue.RDFDatetime.FromSecondsSinceEpoch(42),
current_time,
)

def testWritesAndReadsRDFStringFlowResult(self):
Expand Down Expand Up @@ -2335,7 +2336,8 @@ def testReadResultsRestoresAllFlowResultsFields(self):
)
sample_result.payload.Pack(jobs_pb2.ClientSummary(client_id=client_id))

with test_lib.FakeTime(42):
current_time = rdfvalue.RDFDatetime.Now()
with test_lib.FakeTime(current_time):
self.db.WriteFlowResults([sample_result])

results = self.db.ReadFlowResults(client_id, flow_id, 0, 100)
Expand All @@ -2346,7 +2348,7 @@ def testReadResultsRestoresAllFlowResultsFields(self):
self.assertEqual(results[0].payload, sample_result.payload)
self.assertEqual(
rdfvalue.RDFDatetime.FromMicrosecondsSinceEpoch(results[0].timestamp),
rdfvalue.RDFDatetime.FromSecondsSinceEpoch(42),
current_time,
)

def testWritesAndReadsMultipleFlowResultsOfSingleType(self):
Expand Down Expand Up @@ -2743,17 +2745,16 @@ def testWritesAndReadsSingleFlowErrorOfSingleType(self):
sample_error = flows_pb2.FlowError(client_id=client_id, flow_id=flow_id)
sample_error.payload.Pack(jobs_pb2.ClientSummary(client_id=client_id))

with test_lib.FakeTime(42):
current_time = rdfvalue.RDFDatetime.Now()
with test_lib.FakeTime(current_time):
self.db.WriteFlowErrors([sample_error])

errors = self.db.ReadFlowErrors(client_id, flow_id, 0, 100)
self.assertLen(errors, 1)
self.assertEqual(errors[0].payload, sample_error.payload)
self.assertEqual(
errors[0].timestamp,
rdfvalue.RDFDatetime.FromSecondsSinceEpoch(
42
).AsMicrosecondsSinceEpoch(),
current_time.AsMicrosecondsSinceEpoch(),
)

def testWritesAndReadsMultipleFlowErrorsOfSingleType(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def testMessageHandlerRequestLeasing(self):
m.ClearField("timestamp")
got += l
self.db.DeleteMessageHandlerRequests(got)
self.db.UnregisterMessageHandler()

got.sort(key=lambda req: req.request_id)
self.assertEqual(requests, got)
Expand Down
2 changes: 2 additions & 0 deletions grr/server/grr_response_server/databases/registry_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@

from grr_response_server.databases import mem
from grr_response_server.databases import mysql
from grr_response_server.databases import spanner

# All available databases go into this registry.
REGISTRY = {
"InMemoryDB": mem.InMemoryDB,
"MysqlDB": mysql.MysqlDB,
"SpannerDB": spanner.SpannerDB.FromConfig,
}
80 changes: 80 additions & 0 deletions grr/server/grr_response_server/databases/spanner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# GRR on Spanner

When operating GRR you need to decide on a persistence store.

This document describes how to use [Spanner](https://cloud.google.com/spanner)
as the GRR datastore.

Spanner is a fully managed, mission-critical database service on
[Google Cloud](https://cloud.google.com) that brings together relational, graph,
key-value, and search. It offers transactional consistency at global scale,
automatic, synchronous replication for high availability.

## 1. Google Cloud Resources

Running GRR on Spanner requires that you create and configure a
[Spanner instance](https://cloud.google.com/spanner/docs/instances) before you
run GRR.

Furthermore, you also need to create a
[Google Cloud Storage](https://cloud.google.com/storage)
[Bucket](https://cloud.google.com/storage/docs/buckets) that
will serve as the GRR blobstore.

## 2. Google Cloud Spanner Instance

You can follow the instructions in the Google Cloud online documentation to
[create a Spanner instance](https://cloud.google.com/spanner/docs/create-query-database-console#create-instance).

> [!NOTE] You only need to create the
> [Spanner instance](https://cloud.google.com/spanner/docs/instances). The
> GRR [Spanner database](https://cloud.google.com/spanner/docs/databases)
> and its tables are created by running the provided [spanner_setup.sh](./spanner_setup.sh)
> script. The script assumes that you use `grr-instance` as the
> GRR instance name and `grr-database` as the GRR database name. In
> case you want to use different values then you need to update the
> [spanner_setup.sh](./spanner_setup.sh) script accordingly.
> The script assumes that you have the
> [gcloud](https://cloud.google.com/sdk/docs/install) and the
> [protoc](https://protobuf.dev/installation/) binaries installed on your machine.

Run the following command to create the GRR database and its tables:

```bash
export PROJECT_ID=<YOUR_PROJECT_ID_HERE>
export SPANNER_INSTANCE=grr-instance
export SPANNER_DATABASE=grr-database
./spanner_setup.sh
```

## 3. GRR Configuration

To run GRR on Spanner you need to configure the components settings with
the values of the Google Cloud Spanner and the GCS Bucket resources mentioned above.

The snippet below illustrates a sample GRR `server.yaml` configuration.

```bash
Database.implementation: SpannerDB
Spanner.project: <YOUR_PROJECT_ID_HERE>
Spanner.instance: grr-instance
Spanner.database: grr-database
Blobstore.implementation: GCSBlobStore
Blobstore.gcs.project: <YOUR_PROJECT_ID_HERE>
Blobstore.gcs.bucket: <YOUR_GCS_BUCKET_NAME_HERE>
```

> [!NOTE] Make sure you remove all the `Mysql` related configuration items.

## 4. IAM Permissions

This guide assumes that your GRR instance is running on the [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine) (GKE)
and you can leverage [Workload Identity Federation for GKE](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity) (WIF).

Using WIF you can assign the required IAM roles using the WIF principal
`principal://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<PROJECT_ID.svc.id.goog/subject/ns/<K8S_NAMESPACE>/sa/<K8S_SERVICE_ACCOUNT>`
where `K8S_NAMESPACE` is the value of the Kubernetes Namespace and `K8S_SERVICE_ACCOUNT` is the value Kubernetes Service Account that your GRR Pods are running under.

The two IAM roles that are required are:
- `roles/spanner.databaseUser` on your Spanner Database and
- `roles/storage.objectUser` on our GCS Bucket (the GRR Blobstore mentioned above).
Loading
Loading