Enforce signed backup evidence before migrations
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://govoplan.add-ideas.de/schemas/backup-evidence-v1.json",
|
||||
"title": "GovOPlaN coordinated backup and restore evidence",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schema_version",
|
||||
"evidence_id",
|
||||
"installation_id",
|
||||
"deployment_subject",
|
||||
"release",
|
||||
"recovery_point",
|
||||
"components",
|
||||
"restore_drill",
|
||||
"issued_at",
|
||||
"expires_at",
|
||||
"revoked",
|
||||
"signatures"
|
||||
],
|
||||
"properties": {
|
||||
"schema_version": { "const": "1" },
|
||||
"evidence_id": { "$ref": "#/$defs/token" },
|
||||
"installation_id": { "$ref": "#/$defs/token" },
|
||||
"deployment_subject": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["profile", "topology", "subject_ref"],
|
||||
"properties": {
|
||||
"profile": { "enum": ["evaluation", "self-hosted"] },
|
||||
"topology": { "$ref": "#/$defs/token" },
|
||||
"subject_ref": { "$ref": "#/$defs/reference" }
|
||||
}
|
||||
},
|
||||
"release": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"channel",
|
||||
"version",
|
||||
"manifest_sha256",
|
||||
"composition_sha256",
|
||||
"api_image",
|
||||
"web_image"
|
||||
],
|
||||
"properties": {
|
||||
"channel": { "$ref": "#/$defs/token" },
|
||||
"version": { "$ref": "#/$defs/token" },
|
||||
"manifest_sha256": { "$ref": "#/$defs/sha256" },
|
||||
"composition_sha256": { "$ref": "#/$defs/sha256" },
|
||||
"api_image": { "$ref": "#/$defs/digest_image" },
|
||||
"web_image": { "$ref": "#/$defs/digest_image" }
|
||||
}
|
||||
},
|
||||
"recovery_point": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["id", "captured_at", "consistency", "rpo_seconds", "write_fence"],
|
||||
"properties": {
|
||||
"id": { "$ref": "#/$defs/token" },
|
||||
"captured_at": { "type": "string", "format": "date-time" },
|
||||
"consistency": {
|
||||
"enum": ["provider-atomic", "application-quiesced", "transaction-consistent"]
|
||||
},
|
||||
"rpo_seconds": { "$ref": "#/$defs/duration" },
|
||||
"write_fence": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["mode", "token_sha256", "established_at"],
|
||||
"properties": {
|
||||
"mode": {
|
||||
"enum": ["provider-snapshot", "application-quiesce", "transaction-boundary"]
|
||||
},
|
||||
"token_sha256": { "$ref": "#/$defs/sha256" },
|
||||
"established_at": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["database", "objects", "configuration", "key_custody"],
|
||||
"properties": {
|
||||
"database": { "$ref": "#/$defs/database" },
|
||||
"objects": { "$ref": "#/$defs/objects" },
|
||||
"configuration": { "$ref": "#/$defs/configuration" },
|
||||
"key_custody": { "$ref": "#/$defs/key_custody" }
|
||||
}
|
||||
},
|
||||
"restore_drill": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"drill_id",
|
||||
"recovery_point_id",
|
||||
"started_at",
|
||||
"completed_at",
|
||||
"isolated_target_ref",
|
||||
"release_manifest_sha256",
|
||||
"migration_heads_sha256",
|
||||
"representative_object_manifest_sha256",
|
||||
"database_verified",
|
||||
"objects_verified",
|
||||
"configuration_verified",
|
||||
"key_custody_verified",
|
||||
"semantic_checks",
|
||||
"measured_rpo_seconds",
|
||||
"measured_rto_seconds",
|
||||
"evidence_ref"
|
||||
],
|
||||
"properties": {
|
||||
"drill_id": { "$ref": "#/$defs/token" },
|
||||
"recovery_point_id": { "$ref": "#/$defs/token" },
|
||||
"started_at": { "type": "string", "format": "date-time" },
|
||||
"completed_at": { "type": "string", "format": "date-time" },
|
||||
"isolated_target_ref": { "$ref": "#/$defs/reference" },
|
||||
"release_manifest_sha256": { "$ref": "#/$defs/sha256" },
|
||||
"migration_heads_sha256": { "$ref": "#/$defs/sha256" },
|
||||
"representative_object_manifest_sha256": { "$ref": "#/$defs/sha256" },
|
||||
"database_verified": { "const": true },
|
||||
"objects_verified": { "const": true },
|
||||
"configuration_verified": { "const": true },
|
||||
"key_custody_verified": { "const": true },
|
||||
"semantic_checks": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"maxItems": 128,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["id", "status", "evidence_ref"],
|
||||
"properties": {
|
||||
"id": { "$ref": "#/$defs/token" },
|
||||
"status": { "const": "passed" },
|
||||
"evidence_ref": { "$ref": "#/$defs/reference" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"measured_rpo_seconds": { "$ref": "#/$defs/duration" },
|
||||
"measured_rto_seconds": { "$ref": "#/$defs/duration" },
|
||||
"evidence_ref": { "$ref": "#/$defs/reference" }
|
||||
}
|
||||
},
|
||||
"issued_at": { "type": "string", "format": "date-time" },
|
||||
"expires_at": { "type": "string", "format": "date-time" },
|
||||
"revoked": { "const": false },
|
||||
"signatures": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"maxItems": 16,
|
||||
"items": { "$ref": "#/$defs/signature" }
|
||||
}
|
||||
},
|
||||
"$defs": {
|
||||
"token": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 128,
|
||||
"pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"
|
||||
},
|
||||
"sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
|
||||
"digest_image": {
|
||||
"type": "string",
|
||||
"maxLength": 300,
|
||||
"pattern": "^[^@\\s]+@sha256:[0-9a-f]{64}$"
|
||||
},
|
||||
"reference": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"maxLength": 2048,
|
||||
"pattern": "^[A-Za-z][A-Za-z0-9+.-]*:[^\\s]+$"
|
||||
},
|
||||
"duration": { "type": "integer", "minimum": 0, "maximum": 2592000 },
|
||||
"protected_key": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"protected": { "const": true },
|
||||
"encryption_key_ref": { "$ref": "#/$defs/reference" },
|
||||
"captured_at": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
},
|
||||
"database": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"provider", "artifact_ref", "artifact_sha256", "snapshot_id", "lsn",
|
||||
"protected", "encryption_key_ref", "captured_at"
|
||||
],
|
||||
"properties": {
|
||||
"provider": { "$ref": "#/$defs/token" },
|
||||
"artifact_ref": { "$ref": "#/$defs/reference" },
|
||||
"artifact_sha256": { "$ref": "#/$defs/sha256" },
|
||||
"snapshot_id": { "$ref": "#/$defs/token" },
|
||||
"lsn": { "type": "string", "minLength": 1, "maxLength": 256 },
|
||||
"protected": { "const": true },
|
||||
"encryption_key_ref": { "$ref": "#/$defs/reference" },
|
||||
"captured_at": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
},
|
||||
"objects": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"provider", "artifact_ref", "manifest_sha256", "version_id",
|
||||
"object_count", "total_bytes", "protected", "encryption_key_ref", "captured_at"
|
||||
],
|
||||
"properties": {
|
||||
"provider": { "$ref": "#/$defs/token" },
|
||||
"artifact_ref": { "$ref": "#/$defs/reference" },
|
||||
"manifest_sha256": { "$ref": "#/$defs/sha256" },
|
||||
"version_id": { "$ref": "#/$defs/token" },
|
||||
"object_count": { "type": "integer", "minimum": 0 },
|
||||
"total_bytes": { "type": "integer", "minimum": 0 },
|
||||
"protected": { "const": true },
|
||||
"encryption_key_ref": { "$ref": "#/$defs/reference" },
|
||||
"captured_at": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
},
|
||||
"configuration": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["artifact_ref", "sha256", "protected", "encryption_key_ref", "captured_at"],
|
||||
"properties": {
|
||||
"artifact_ref": { "$ref": "#/$defs/reference" },
|
||||
"sha256": { "$ref": "#/$defs/sha256" },
|
||||
"protected": { "const": true },
|
||||
"encryption_key_ref": { "$ref": "#/$defs/reference" },
|
||||
"captured_at": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
},
|
||||
"key_custody": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["provider", "keyset_ref", "keyset_version", "recoverable", "captured_at"],
|
||||
"properties": {
|
||||
"provider": { "$ref": "#/$defs/token" },
|
||||
"keyset_ref": { "$ref": "#/$defs/reference" },
|
||||
"keyset_version": { "$ref": "#/$defs/token" },
|
||||
"recoverable": { "const": true },
|
||||
"captured_at": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
},
|
||||
"signature": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["key_id", "algorithm", "value"],
|
||||
"properties": {
|
||||
"key_id": { "$ref": "#/$defs/token" },
|
||||
"algorithm": { "const": "ed25519" },
|
||||
"value": { "type": "string", "minLength": 1, "maxLength": 256 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user