use in_toto_attestation::predicates::provenance::v1::provenance;
use in_toto_attestation::v1::resource_descriptor::ResourceDescriptor;
use protobuf::MessageField;
use protobuf::well_known_types::struct_::Struct;
use protobuf::well_known_types::timestamp::Timestamp;
use std::collections::HashMap;
pub fn make_build_definition_v1(
build_type: &str,
external_parameters: &Struct,
internal_parameters: Option<&Struct>,
resolved_dependencies: Option<&[ResourceDescriptor]>,
) -> provenance::BuildDefinition {
let mut build_def = provenance::BuildDefinition::new();
build_def.build_type = build_type.to_string();
build_def.external_parameters = MessageField::some(external_parameters.clone());
if internal_parameters.is_some() {
build_def.internal_parameters = MessageField::some(internal_parameters.unwrap().clone());
}
if resolved_dependencies.is_some() {
build_def.resolved_dependencies = resolved_dependencies.unwrap().to_vec();
}
build_def
}
pub fn make_builder_v1(
id: &str,
builder_dependencies: Option<&[ResourceDescriptor]>,
version: Option<&HashMap<String, String>>,
) -> provenance::Builder {
let mut builder = provenance::Builder::new();
builder.id = id.to_string();
if builder_dependencies.is_some() {
builder.builder_dependencies = builder_dependencies.unwrap().to_vec();
}
if version.is_some() {
builder.version = version.unwrap().clone();
}
builder
}
pub fn make_build_metadata_v1(
invocation_id: &str,
started_on: Option<&Timestamp>,
finished_on: Option<&Timestamp>,
) -> provenance::BuildMetadata {
let mut build_metadata = provenance::BuildMetadata::new();
build_metadata.invocation_id = invocation_id.to_string();
if started_on.is_some() {
build_metadata.started_on = MessageField::some(started_on.unwrap().clone());
}
if finished_on.is_some() {
build_metadata.finished_on = MessageField::some(finished_on.unwrap().clone());
}
build_metadata
}
pub fn make_run_details_v1(
builder: &provenance::Builder,
metadata: Option<&provenance::BuildMetadata>,
byproducts: Option<&[ResourceDescriptor]>,
) -> provenance::RunDetails {
let mut run_details = provenance::RunDetails::new();
run_details.builder = MessageField::some(builder.clone());
if metadata.is_some() {
run_details.metadata = MessageField::some(metadata.unwrap().clone());
}
if byproducts.is_some() {
run_details.byproducts = byproducts.unwrap().to_vec();
}
run_details
}
pub fn generate_build_provenance_v1(
build_definition: &provenance::BuildDefinition,
run_details: &provenance::RunDetails,
) -> provenance::Provenance {
let mut provenance = provenance::Provenance::new();
provenance.build_definition = MessageField::some(build_definition.clone());
provenance.run_details = MessageField::some(run_details.clone());
provenance
}
#[cfg(test)]
mod tests {
use super::*;
use crate::slsa::cli::ATLAS_CLI_BUILDER_ID;
#[test]
fn test_make_build_definition_v1_minimal() {
let external_params = Struct::new();
let build_def =
make_build_definition_v1("test-builder:1.0.0", &external_params, None, None);
assert_eq!(build_def.build_type, "test-builder:1.0.0");
assert!(build_def.external_parameters.is_some());
assert!(build_def.internal_parameters.is_none());
assert!(build_def.resolved_dependencies.is_empty());
}
#[test]
fn test_make_build_definition_v1_complete() {
let external_params = Struct::new();
let internal_params = Struct::new();
let dependencies = vec![ResourceDescriptor::new(), ResourceDescriptor::new()];
let build_def = make_build_definition_v1(
"test-builder:1.0.0",
&external_params,
Some(&internal_params),
Some(&dependencies),
);
assert_eq!(build_def.build_type, "test-builder:1.0.0");
assert!(build_def.external_parameters.is_some());
assert!(build_def.internal_parameters.is_some());
assert_eq!(build_def.resolved_dependencies.len(), 2);
}
#[test]
fn test_make_builder_v1_minimal() {
let builder = make_builder_v1("test-builder-id", None, None);
assert_eq!(builder.id, "test-builder-id");
assert!(builder.builder_dependencies.is_empty());
assert!(builder.version.is_empty());
}
#[test]
fn test_make_builder_v1_complete() {
let dependencies = vec![ResourceDescriptor::new()];
let mut version_info = HashMap::new();
version_info.insert("version".to_string(), "2.0.0".to_string());
let builder = make_builder_v1("complete-builder", Some(&dependencies), Some(&version_info));
assert_eq!(builder.id, "complete-builder");
assert_eq!(builder.builder_dependencies.len(), 1);
assert_eq!(builder.version.len(), 1);
assert_eq!(builder.version.get("version"), Some(&"2.0.0".to_string()));
}
#[test]
fn test_make_build_metadata_v1_minimal() {
let metadata = make_build_metadata_v1("test-invocation-123", None, None);
assert_eq!(metadata.invocation_id, "test-invocation-123");
assert!(metadata.started_on.is_none());
assert!(metadata.finished_on.is_none());
}
#[test]
fn test_make_build_metadata_v1_complete() {
let start_time = Timestamp::now();
let end_time = Timestamp::now();
let metadata = make_build_metadata_v1(
"complete-build-uuid-456",
Some(&start_time),
Some(&end_time),
);
assert_eq!(metadata.invocation_id, "complete-build-uuid-456");
assert!(metadata.started_on.is_some());
assert!(metadata.finished_on.is_some());
}
#[test]
fn test_make_run_details_v1_minimal() {
let builder = make_builder_v1("test-builder", None, None);
let run_details = make_run_details_v1(&builder, None, None);
assert!(run_details.builder.is_some());
assert_eq!(run_details.builder.as_ref().unwrap().id, "test-builder");
assert!(run_details.metadata.is_none());
assert!(run_details.byproducts.is_empty());
}
#[test]
fn test_make_run_details_v1_complete() {
let builder = make_builder_v1("complete-builder", None, None);
let metadata = make_build_metadata_v1("complete-invocation", None, None);
let byproducts = vec![ResourceDescriptor::new()];
let run_details = make_run_details_v1(&builder, Some(&metadata), Some(&byproducts));
assert!(run_details.builder.is_some());
assert_eq!(run_details.builder.as_ref().unwrap().id, "complete-builder");
assert!(run_details.metadata.is_some());
assert_eq!(
run_details.metadata.as_ref().unwrap().invocation_id,
"complete-invocation"
);
assert_eq!(run_details.byproducts.len(), 1);
}
#[test]
fn test_generate_build_provenance_v1_minimal() {
let external_params = Struct::new();
let build_def = make_build_definition_v1("test:1.0", &external_params, None, None);
let builder = make_builder_v1("test-builder", None, None);
let run_details = make_run_details_v1(&builder, None, None);
let provenance = generate_build_provenance_v1(&build_def, &run_details);
assert!(provenance.build_definition.is_some());
assert!(provenance.run_details.is_some());
assert_eq!(
provenance.build_definition.as_ref().unwrap().build_type,
"test:1.0"
);
assert_eq!(
provenance
.run_details
.as_ref()
.unwrap()
.builder
.as_ref()
.unwrap()
.id,
"test-builder"
);
}
#[test]
fn test_generate_build_provenance_v1_complete() {
let external_params = Struct::new();
let internal_params = Struct::new();
let dependencies = vec![ResourceDescriptor::new()];
let build_def = make_build_definition_v1(
"atlas-cli:1.0.0",
&external_params,
Some(&internal_params),
Some(&dependencies),
);
let mut version_info = HashMap::new();
version_info.insert("version".to_string(), "1.0.0".to_string());
let builder_deps = vec![ResourceDescriptor::new()];
let builder = make_builder_v1(
ATLAS_CLI_BUILDER_ID,
Some(&builder_deps),
Some(&version_info),
);
let start_time = Timestamp::now();
let end_time = Timestamp::now();
let metadata = make_build_metadata_v1("complete-build", Some(&start_time), Some(&end_time));
let byproducts = vec![ResourceDescriptor::new(), ResourceDescriptor::new()];
let run_details = make_run_details_v1(&builder, Some(&metadata), Some(&byproducts));
let provenance = generate_build_provenance_v1(&build_def, &run_details);
assert!(provenance.build_definition.is_some());
assert!(provenance.run_details.is_some());
let build_def_ref = provenance.build_definition.as_ref().unwrap();
assert_eq!(build_def_ref.build_type, "atlas-cli:1.0.0");
assert!(build_def_ref.external_parameters.is_some());
assert!(build_def_ref.internal_parameters.is_some());
assert_eq!(build_def_ref.resolved_dependencies.len(), 1);
let run_details_ref = provenance.run_details.as_ref().unwrap();
assert!(run_details_ref.builder.is_some());
assert!(run_details_ref.metadata.is_some());
assert_eq!(run_details_ref.byproducts.len(), 2);
let builder_ref = run_details_ref.builder.as_ref().unwrap();
assert_eq!(builder_ref.id, ATLAS_CLI_BUILDER_ID);
assert_eq!(builder_ref.builder_dependencies.len(), 1);
assert_eq!(builder_ref.version.len(), 1);
let metadata_ref = run_details_ref.metadata.as_ref().unwrap();
assert_eq!(metadata_ref.invocation_id, "complete-build");
assert!(metadata_ref.started_on.is_some());
assert!(metadata_ref.finished_on.is_some());
}
}