Repository: google/exposure-notifications-server
Pull request #1274 (2021-01-08 22:34:59)

ensure imported keys are future dated

## Proposed Changes

* for imported keys - future date them if not expired. Works around potential bugs in upstream systems
* put created at date for published future dated keys into the NEXT interval. 

**Release Note**

```release-note
Imported keys will be future dated if they haven't expired yet.
Published keys will be moved forward one extra interval when they are adjusted. **There is no actual issue here with the default configuration because of the additional 2 hour embargo, but this is more technically correct.**
```

google-oss-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/google/exposure-notifications-server/pull/1274#" title="Author self-approved">mikehelmick</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=google%2Fexposure-notifications-server).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/google/exposure-notifications-server/blob/main/OWNERS)~~ [mikehelmick]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
google-oss-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/google/exposure-notifications-server/pull/1274#" title="Author self-approved">mikehelmick</a>*, *<a href="https://github.com/google/exposure-notifications-server/pull/1274#pullrequestreview-564630102" title="LGTM">sethvargo</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=google%2Fexposure-notifications-server).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/google/exposure-notifications-server/blob/main/OWNERS)~~ [mikehelmick,sethvargo]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->

Patch:
diff --git a/internal/exportimport/import.go b/internal/exportimport/import.go
index e63c4b4..24f3a25 100644
--- a/internal/exportimport/import.go
+++ b/internal/exportimport/import.go
@@ -142,6 +142,7 @@ func (s *Server) ImportExportFile(ctx context.Context, ir *ImportRequest) (*Impo
 		appPackageName: s.config.ImportAPKName,
 		importRegions:  []string{ir.exportImport.Region},
 		batchTime:      time.Now().UTC().Truncate(s.config.CreatedAtTruncateWindow),
+		truncateWindow: s.config.CreatedAtTruncateWindow,
 		exportImportID: ir.exportImport.ID,
 		importFileID:   ir.file.ID,
 		exportImportConfig: &pubmodel.ExportImportConfig{
@@ -218,6 +219,7 @@ type transformer struct {
 	appPackageName     string
 	importRegions      []string
 	batchTime          time.Time
+	truncateWindow     time.Duration
 	exportImportID     int64
 	importFileID       int64
 	exportImportConfig *pubmodel.ExportImportConfig
@@ -242,6 +244,11 @@ func (t *transformer) transform(keys []*exportproto.TemporaryExposureKey) ([]*pu
 		exp.ExportImportID = &t.exportImportID
 		exp.ImportFileID = &t.importFileID
 
+		// Adjust created at time, if this key is not yet expired.
+		if expTime := pubmodel.TimeForIntervalNumber(exp.IntervalNumber + exp.IntervalCount); expTime.Before(exp.CreatedAt) {
+			exp.CreatedAt = exp.CreatedAt.Add(t.truncateWindow).Truncate(t.truncateWindow)
+		}
+
 		inserts = append(inserts, exp)
 	}
 	return inserts, dropped
diff --git a/internal/publish/model/exposure_model.go b/internal/publish/model/exposure_model.go
index 7696d36..f0125ed 100644
--- a/internal/publish/model/exposure_model.go
+++ b/internal/publish/model/exposure_model.go
@@ -354,7 +354,8 @@ func (e *Exposure) AdjustAndValidate(settings *KeyTransform) error {
 	if e.IntervalNumber+e.IntervalCount > settings.MaxStartInterval {
 		// key is still valid. The created At for this key needs to be adjusted unless debugging is enabled.
 		if !settings.ReleaseStillValidKeys {
-			e.CreatedAt = TimeForIntervalNumber(e.IntervalNumber + e.IntervalCount).Truncate(settings.BatchWindow)
+			// The add of the batch window is to ensure that the created at time is after the expiry.
+			e.CreatedAt = TimeForIntervalNumber(e.IntervalNumber + e.IntervalCount).Add(settings.BatchWindow).Truncate(settings.BatchWindow)
 		}
 	}
 


Test patch:
diff --git a/internal/publish/model/exposure_model_test.go b/internal/publish/model/exposure_model_test.go
index f01c0b5..b5fb96d 100644
--- a/internal/publish/model/exposure_model_test.go
+++ b/internal/publish/model/exposure_model_test.go
@@ -412,7 +412,7 @@ func TestStillValidKey(t *testing.T) {
 					},
 				},
 			},
-			createdAt:          TruncateWindow(TimeForIntervalNumber(intervalNumber+verifyapi.MaxIntervalCount), time.Minute),
+			createdAt:          TruncateWindow(TimeForIntervalNumber(intervalNumber+verifyapi.MaxIntervalCount).Add(time.Minute), time.Minute),
 			releaseSameDayKeys: false,
 		},
 	}