From 719c3d85379ecd954b9765d1ac226c10adc42548 Mon Sep 17 00:00:00 2001 From: RZandvoort <25634703+RZandvoort@users.noreply.github.com> Date: Wed, 7 Feb 2024 16:32:29 +0100 Subject: [PATCH 01/21] Add functionality --- serviceinfo-api-server/src/main.rs | 145 ++++++++++++++++++++++------- 1 file changed, 113 insertions(+), 32 deletions(-) diff --git a/serviceinfo-api-server/src/main.rs b/serviceinfo-api-server/src/main.rs index ec0dc6f64..f3172ca31 100644 --- a/serviceinfo-api-server/src/main.rs +++ b/serviceinfo-api-server/src/main.rs @@ -28,39 +28,42 @@ impl ServiceInfoConfiguration { // Perform checks on the configuration // Check permissions for files are valid - settings.files = if let Some(files) = settings.files { - let mut new_files = Vec::new(); - - for mut file in files { - let path = &file.path; - - file.parsed_permissions = if let Some(permissions) = &file.permissions { - Some(u32::from_str_radix(permissions, 8).with_context(|| { - format!( - "Invalid permission string for file {path}: {permissions} (invalid octal)" - ) - })?) - } else { - None - }; - - let contents = std::fs::read(&file.source_path) - .with_context(|| format!("Failed to read file {}", file.source_path))?; - file.hash_hex = hex::encode( - Hash::from_data(HashType::Sha384, &contents) - .with_context(|| format!("Failed to hash file {}", file.source_path))? - .value_bytes(), - ); - file.contents_len = contents.len(); - file.contents_hex = hex::encode(&contents); - new_files.push(file); - } - - Some(new_files) - } else { - None - }; + //// TODO: enchance_files() + check_file_configuration(settings.files); + // settings.files = if let Some(files) = settings.files { + // let mut new_files = Vec::new(); + + // for mut file in files { + // let path = &file.path; + + // file.parsed_permissions = if let Some(permissions) = &file.permissions { + // Some(u32::from_str_radix(permissions, 8).with_context(|| { + // format!( + // "Invalid permission string for file {path}: {permissions} (invalid octal)" + // ) + // })?) + // } else { + // None + // }; + + // let contents = std::fs::read(&file.source_path) + // .with_context(|| format!("Failed to read file {}", file.source_path))?; + // file.hash_hex = hex::encode( + // Hash::from_data(HashType::Sha384, &contents) + // .with_context(|| format!("Failed to hash file {}", file.source_path))? + // .value_bytes(), + // ); + // file.contents_len = contents.len(); + // file.contents_hex = hex::encode(&contents); + + // new_files.push(file); + // } + + // Some(new_files) + // } else { + // None + // }; Ok(ServiceInfoConfiguration { settings }) } @@ -286,6 +289,46 @@ async fn serviceinfo_handler( ); } } + + // precedence is given to 'per_device' settings over base serviceinfo_api_server.yml config + match settings_per_device(&query_info.device_guid.to_string().replace('\"', "")) { + Ok(config) => { + let per_device_settings = config; + if let Some(initial_user) = &per_device_settings.files { + check_file_configuration(&per_device_settings.files); + + // Adding per device files config + for file in files { + reply.add_extra(FedoraIotServiceInfoModule::BinaryFile, "name", &file.path); + reply.add_extra( + FedoraIotServiceInfoModule::BinaryFile, + "length", + &file.contents_len, + ); + if let Some(parsed_permissions) = &file.parsed_permissions { + reply.add_extra( + FedoraIotServiceInfoModule::BinaryFile, + "mode", + &parsed_permissions, + ); + } + reply.add_extra( + FedoraIotServiceInfoModule::BinaryFile, + "data001|hex", + &file.contents_hex, + ); + reply.add_extra( + FedoraIotServiceInfoModule::BinaryFile, + "sha-384|hex", + &file.hash_hex, + ); + } + } + } + Err(_) => { + log::info!("per-device settings file not available, so loading base config file"); + } + }; } if query_info @@ -390,6 +433,44 @@ async fn serviceinfo_handler( Ok(warp::reply::json(&reply.reply)) } +fn check_file_configuration(mut files: Vec) { + settings.files = if let Some(files) = settings.files { + let mut new_files = Vec::new(); + + for mut file in files { + let path = &file.path; + + file.parsed_permissions = if let Some(permissions) = &file.permissions { + Some(u32::from_str_radix(permissions, 8).with_context(|| { + format!( + "Invalid permission string for file {path}: {permissions} (invalid octal)" + ) + })?) + } else { + None + }; + + let contents = std::fs::read(&file.source_path) + .with_context(|| format!("Failed to read file {}", file.source_path))?; + file.hash_hex = hex::encode( + Hash::from_data(HashType::Sha384, &contents) + .with_context(|| format!("Failed to hash file {}", file.source_path))? + .value_bytes(), + ); + file.contents_len = contents.len(); + file.contents_hex = hex::encode(&contents); + + new_files.push(file); + } + + Some(new_files) + } else { + None + }; + + Ok(ServiceInfoConfiguration { settings }) +} + fn deserialize_from_str<'de, D>(deserializer: D) -> Result where D: serde::de::Deserializer<'de>, From 15c43ba57b2a779a0ab50810297ef6162515368b Mon Sep 17 00:00:00 2001 From: RZandvoort <25634703+RZandvoort@users.noreply.github.com> Date: Fri, 9 Feb 2024 15:01:09 +0100 Subject: [PATCH 02/21] Update main.rs --- serviceinfo-api-server/src/main.rs | 101 ++++++++++++++++------------- 1 file changed, 55 insertions(+), 46 deletions(-) diff --git a/serviceinfo-api-server/src/main.rs b/serviceinfo-api-server/src/main.rs index f3172ca31..8e95aaa00 100644 --- a/serviceinfo-api-server/src/main.rs +++ b/serviceinfo-api-server/src/main.rs @@ -5,7 +5,7 @@ use fdo_data_formats::{ }; use fdo_store::Store; use fdo_util::servers::{ - configuration::serviceinfo_api_server::{ServiceInfoApiServerSettings, ServiceInfoSettings}, + configuration::serviceinfo_api_server::{ServiceInfoApiServerSettings, ServiceInfoSettings, ServiceInfoFile}, settings_for, settings_per_device, ServiceInfoApiReply, ServiceInfoApiReplyInitialUser, ServiceInfoApiReplyReboot, }; @@ -23,14 +23,20 @@ struct ServiceInfoConfiguration { settings: ServiceInfoSettings, } +// #[derive(Debug)] +// struct ServiceInfoFiles { +// files: Vec, +// } + impl ServiceInfoConfiguration { - fn from_settings(mut settings: ServiceInfoSettings) -> Result { + fn from_settings(settings: ServiceInfoSettings) -> Result { // Perform checks on the configuration // Check permissions for files are valid - //// TODO: enchance_files() - check_file_configuration(settings.files); + //// TODO: do something with result? + let _ = check_file_configuration(settings.files.clone()); + // settings.files = if let Some(files) = settings.files { // let mut new_files = Vec::new(); @@ -69,6 +75,44 @@ impl ServiceInfoConfiguration { } } +// fn check_file_configuration(mut files_to_check: Option>) -> Result> { +fn check_file_configuration(mut files_to_check: Option>) -> Result>> { + files_to_check = if let Some(files) = files_to_check { + let mut new_files = Vec::new(); + + for mut file in files { + let path = &file.path; + + file.parsed_permissions = if let Some(permissions) = &file.permissions { + Some(u32::from_str_radix(permissions, 8).with_context(|| { + format!( + "Invalid permission string for file {path}: {permissions} (invalid octal)" + ) + })?) + } else { + None + }; + + let contents = std::fs::read(&file.source_path) + .with_context(|| format!("Failed to read file {}", file.source_path))?; + file.hash_hex = hex::encode( + Hash::from_data(HashType::Sha384, &contents) + .with_context(|| format!("Failed to hash file {}", file.source_path))? + .value_bytes(), + ); + file.contents_len = contents.len(); + file.contents_hex = hex::encode(&contents); + + new_files.push(file); + } + + Some(new_files) + } else { + None + }; + Ok( files_to_check ) +} + #[derive(Debug, Clone, Copy)] #[non_exhaustive] enum ServiceInfoMetadataKey {} @@ -293,10 +337,13 @@ async fn serviceinfo_handler( // precedence is given to 'per_device' settings over base serviceinfo_api_server.yml config match settings_per_device(&query_info.device_guid.to_string().replace('\"', "")) { Ok(config) => { - let per_device_settings = config; - if let Some(initial_user) = &per_device_settings.files { - check_file_configuration(&per_device_settings.files); - + let per_device_settings = config.clone(); + let per_device_settings1 = config; + + // TODO: do something with result? + let _ = check_file_configuration(per_device_settings1.files); + + if let Some(files) = &per_device_settings.files { // Adding per device files config for file in files { reply.add_extra(FedoraIotServiceInfoModule::BinaryFile, "name", &file.path); @@ -433,44 +480,6 @@ async fn serviceinfo_handler( Ok(warp::reply::json(&reply.reply)) } -fn check_file_configuration(mut files: Vec) { - settings.files = if let Some(files) = settings.files { - let mut new_files = Vec::new(); - - for mut file in files { - let path = &file.path; - - file.parsed_permissions = if let Some(permissions) = &file.permissions { - Some(u32::from_str_radix(permissions, 8).with_context(|| { - format!( - "Invalid permission string for file {path}: {permissions} (invalid octal)" - ) - })?) - } else { - None - }; - - let contents = std::fs::read(&file.source_path) - .with_context(|| format!("Failed to read file {}", file.source_path))?; - file.hash_hex = hex::encode( - Hash::from_data(HashType::Sha384, &contents) - .with_context(|| format!("Failed to hash file {}", file.source_path))? - .value_bytes(), - ); - file.contents_len = contents.len(); - file.contents_hex = hex::encode(&contents); - - new_files.push(file); - } - - Some(new_files) - } else { - None - }; - - Ok(ServiceInfoConfiguration { settings }) -} - fn deserialize_from_str<'de, D>(deserializer: D) -> Result where D: serde::de::Deserializer<'de>, From 9ed790e56a1ea8ad1900bdd2310af48763d40955 Mon Sep 17 00:00:00 2001 From: RZandvoort <25634703+RZandvoort@users.noreply.github.com> Date: Fri, 9 Feb 2024 15:04:19 +0100 Subject: [PATCH 03/21] Update cd.yml --- .github/workflows/cd.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 48a964fac..77c8ad623 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,8 +1,5 @@ on: push: - branches: - - main - - "*.*.x" tags: - v* schedule: From 29a22a973e9cb3dd3f3e78032f44d3ad039458a0 Mon Sep 17 00:00:00 2001 From: RZandvoort <25634703+RZandvoort@users.noreply.github.com> Date: Fri, 9 Feb 2024 15:05:12 +0100 Subject: [PATCH 04/21] Update cd.yml --- .github/workflows/cd.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 77c8ad623..ce4ee7f97 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,7 +1,5 @@ on: push: - tags: - - v* schedule: - cron: '0 0 * * *' From 16035322705f2a2d86a110be8093d0a4a14b0df6 Mon Sep 17 00:00:00 2001 From: RZandvoort <25634703+RZandvoort@users.noreply.github.com> Date: Fri, 9 Feb 2024 15:18:21 +0100 Subject: [PATCH 05/21] Update cd.yml --- .github/workflows/cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index ce4ee7f97..24a1f0d0c 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -22,7 +22,7 @@ jobs: - name: Push admin-cli to quay.io uses: redhat-actions/push-to-registry@v2 with: - registry: "quay.io/${{ env.quay_org }}" + registry: "quay.io/kpwrwyfmyzpxupsign" image: admin-cli tags: ${{ steps.build.outputs.tags }} username: ${{ secrets.QUAY_USERNAME }} From bdf098dadf7814828e67f568ec72e19a87673770 Mon Sep 17 00:00:00 2001 From: RZandvoort <25634703+RZandvoort@users.noreply.github.com> Date: Fri, 9 Feb 2024 15:34:17 +0100 Subject: [PATCH 06/21] Update action.yml --- .github/actions/build_containers/action.yml | 55 --------------------- 1 file changed, 55 deletions(-) diff --git a/.github/actions/build_containers/action.yml b/.github/actions/build_containers/action.yml index c77ab9061..6450cb0cb 100644 --- a/.github/actions/build_containers/action.yml +++ b/.github/actions/build_containers/action.yml @@ -68,50 +68,6 @@ runs: tags: fdo-build:${{ steps.buildid.outputs.buildid }} containerfiles: contrib/containers/build - - name: Create admin-cli container - uses: redhat-actions/buildah-build@v2 - with: - containerfiles: contrib/containers/admin-cli - tags: | - ${{ format(steps.container-metadata.outputs.tags, 'admin-cli') }} - admin-cli:${{ steps.buildid.outputs.buildid }} - labels: ${{ steps.container-metadata.outputs.labels }} - build-args: | - BUILDID=${{ steps.buildid.outputs.buildid }} - - - name: Create manufacturing-server container - uses: redhat-actions/buildah-build@v2 - with: - containerfiles: contrib/containers/manufacturing-server - tags: | - ${{ format(steps.container-metadata.outputs.tags, 'manufacturing-server') }} - manufacturing-server:${{ steps.buildid.outputs.buildid }} - labels: ${{ steps.container-metadata.outputs.labels }} - build-args: | - BUILDID=${{ steps.buildid.outputs.buildid }} - - - name: Create aio container - uses: redhat-actions/buildah-build@v2 - with: - containerfiles: contrib/containers/aio - tags: | - ${{ format(steps.container-metadata.outputs.tags, 'aio') }} - aio:${{ steps.buildid.outputs.buildid }} - labels: ${{ steps.container-metadata.outputs.labels }} - build-args: | - BUILDID=${{ steps.buildid.outputs.buildid }} - - - name: Create rendezvous-server container - uses: redhat-actions/buildah-build@v2 - with: - containerfiles: contrib/containers/rendezvous-server - tags: | - ${{ format(steps.container-metadata.outputs.tags, 'rendezvous-server') }} - rendezvous-server:${{ steps.buildid.outputs.buildid }} - labels: ${{ steps.container-metadata.outputs.labels }} - build-args: | - BUILDID=${{ steps.buildid.outputs.buildid }} - - name: Create serviceinfo-api-server container uses: redhat-actions/buildah-build@v2 with: @@ -123,17 +79,6 @@ runs: build-args: | BUILDID=${{ steps.buildid.outputs.buildid }} - - name: Create owner-onboarding-server container - uses: redhat-actions/buildah-build@v2 - with: - containerfiles: contrib/containers/owner-onboarding-server - tags: | - ${{ format(steps.container-metadata.outputs.tags, 'owner-onboarding-server') }} - owner-onboarding-server:${{ steps.buildid.outputs.buildid }} - labels: ${{ steps.container-metadata.outputs.labels }} - build-args: | - BUILDID=${{ steps.buildid.outputs.buildid }} - - name: Create client-linuxapp container uses: redhat-actions/buildah-build@v2 with: From c2111c0a4b6e72d9b6a2c92eb2bab363a3ebec28 Mon Sep 17 00:00:00 2001 From: RZandvoort <25634703+RZandvoort@users.noreply.github.com> Date: Fri, 9 Feb 2024 15:36:53 +0100 Subject: [PATCH 07/21] Update cd.yml --- .github/workflows/cd.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 24a1f0d0c..a8340c772 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,7 +1,6 @@ on: push: - schedule: - - cron: '0 0 * * *' + workflow_dispatch: name: Continuous Delivery From 2f3b530d57dce9be2dd48489d91d9f25dba24d22 Mon Sep 17 00:00:00 2001 From: RZandvoort <25634703+RZandvoort@users.noreply.github.com> Date: Fri, 9 Feb 2024 15:42:03 +0100 Subject: [PATCH 08/21] Update cd.yml --- .github/workflows/cd.yml | 56 +--------------------------------------- 1 file changed, 1 insertion(+), 55 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index a8340c772..4c1c67ec2 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -18,65 +18,11 @@ jobs: id: build uses: ./.github/actions/build_containers - - name: Push admin-cli to quay.io - uses: redhat-actions/push-to-registry@v2 - with: - registry: "quay.io/kpwrwyfmyzpxupsign" - image: admin-cli - tags: ${{ steps.build.outputs.tags }} - username: ${{ secrets.QUAY_USERNAME }} - password: ${{ secrets.QUAY_ROBOT_TOKEN }} - - - name: Push manufacturing-server to quay.io - uses: redhat-actions/push-to-registry@v2 - with: - registry: "quay.io/${{ env.quay_org }}" - image: manufacturing-server - tags: ${{ steps.build.outputs.tags }} - username: ${{ secrets.QUAY_USERNAME }} - password: ${{ secrets.QUAY_ROBOT_TOKEN }} - - - name: Push rendezvous-server to quay.io - uses: redhat-actions/push-to-registry@v2 - with: - registry: "quay.io/${{ env.quay_org }}" - image: rendezvous-server - tags: ${{ steps.build.outputs.tags }} - username: ${{ secrets.QUAY_USERNAME }} - password: ${{ secrets.QUAY_ROBOT_TOKEN }} - - name: Push serviceinfo-api-server to quay.io uses: redhat-actions/push-to-registry@v2 with: - registry: "quay.io/${{ env.quay_org }}" + registry: "quay.io/kpwrwyfmyzpxupsign" image: serviceinfo-api-server tags: ${{ steps.build.outputs.tags }} username: ${{ secrets.QUAY_USERNAME }} password: ${{ secrets.QUAY_ROBOT_TOKEN }} - - - name: Push owner-onboarding-server to quay.io - uses: redhat-actions/push-to-registry@v2 - with: - registry: "quay.io/${{ env.quay_org }}" - image: owner-onboarding-server - tags: ${{ steps.build.outputs.tags }} - username: ${{ secrets.QUAY_USERNAME }} - password: ${{ secrets.QUAY_ROBOT_TOKEN }} - - - name: Push aio to quay.io - uses: redhat-actions/push-to-registry@v2 - with: - registry: "quay.io/${{ env.quay_org }}" - image: aio - tags: ${{ steps.build.outputs.tags }} - username: ${{ secrets.QUAY_USERNAME }} - password: ${{ secrets.QUAY_ROBOT_TOKEN }} - - - name: Push client-linuxapp to quay.io - uses: redhat-actions/push-to-registry@v2 - with: - registry: "quay.io/${{ env.quay_org }}" - image: client-linuxapp - tags: ${{ steps.build.outputs.tags }} - username: ${{ secrets.QUAY_USERNAME }} - password: ${{ secrets.QUAY_ROBOT_TOKEN }} From 4b3a934f6f7a30050655b64b7a770215b16eb18a Mon Sep 17 00:00:00 2001 From: RZandvoort <25634703+RZandvoort@users.noreply.github.com> Date: Fri, 9 Feb 2024 15:52:54 +0100 Subject: [PATCH 09/21] Update action.yml --- .github/actions/build_containers/action.yml | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/.github/actions/build_containers/action.yml b/.github/actions/build_containers/action.yml index 6450cb0cb..709193e97 100644 --- a/.github/actions/build_containers/action.yml +++ b/.github/actions/build_containers/action.yml @@ -46,14 +46,14 @@ runs: allimages="" alltags="" allimagetags="" - for container in admin-cli manufacturing-server rendezvous-server serviceinfo-api-server owner-onboarding-server aio client-linuxapp + for container in serviceinfo-api-server do allimages="$allimages $container" done for tag in "$rawtags" do alltags="$alltags ${tag//imagename:/}" - for container in admin-cli manufacturing-server rendezvous-server serviceinfo-api-server owner-onboarding-server aio client-linuxapp + for container in serviceinfo-api-server do allimagetags="$allimagetags ${tag//imagename/"$container"}" done @@ -79,21 +79,10 @@ runs: build-args: | BUILDID=${{ steps.buildid.outputs.buildid }} - - name: Create client-linuxapp container - uses: redhat-actions/buildah-build@v2 - with: - containerfiles: contrib/containers/client-linuxapp - tags: | - ${{ format(steps.container-metadata.outputs.tags, 'client-linuxapp') }} - client-linuxapp:${{ steps.buildid.outputs.buildid }} - labels: ${{ steps.container-metadata.outputs.labels }} - build-args: | - BUILDID=${{ steps.buildid.outputs.buildid }} - - name: Test containers shell: bash run: | - for container in admin-cli manufacturing-server rendezvous-server serviceinfo-api-server owner-onboarding-server aio client-linuxapp + for container in serviceinfo-api-server do podman run --rm $container:${{ steps.buildid.outputs.buildid }} --version done From a83f9747ddc682102a583a25742dd2fa1ad80f35 Mon Sep 17 00:00:00 2001 From: RZandvoort <25634703+RZandvoort@users.noreply.github.com> Date: Fri, 9 Feb 2024 16:55:51 +0100 Subject: [PATCH 10/21] Update main.rs --- serviceinfo-api-server/src/main.rs | 161 +++++++++++++++-------------- 1 file changed, 85 insertions(+), 76 deletions(-) diff --git a/serviceinfo-api-server/src/main.rs b/serviceinfo-api-server/src/main.rs index 8e95aaa00..1dc26bc63 100644 --- a/serviceinfo-api-server/src/main.rs +++ b/serviceinfo-api-server/src/main.rs @@ -29,89 +29,98 @@ struct ServiceInfoConfiguration { // } impl ServiceInfoConfiguration { - fn from_settings(settings: ServiceInfoSettings) -> Result { + fn from_settings(mut settings: ServiceInfoSettings) -> Result { // Perform checks on the configuration // Check permissions for files are valid + settings.files = if let Some(files) = settings.files { + let mut new_files = Vec::new(); + + for mut file in files { + let path = &file.path; + + file.parsed_permissions = if let Some(permissions) = &file.permissions { + Some(u32::from_str_radix(permissions, 8).with_context(|| { + format!( + "Invalid permission string for file {path}: {permissions} (invalid octal)" + ) + })?) + } else { + None + }; + + let contents = std::fs::read(&file.source_path) + .with_context(|| format!("Failed to read file {}", file.source_path))?; + file.hash_hex = hex::encode( + Hash::from_data(HashType::Sha384, &contents) + .with_context(|| format!("Failed to hash file {}", file.source_path))? + .value_bytes(), + ); + file.contents_len = contents.len(); + file.contents_hex = hex::encode(&contents); + + new_files.push(file); + } - //// TODO: do something with result? - let _ = check_file_configuration(settings.files.clone()); - - // settings.files = if let Some(files) = settings.files { - // let mut new_files = Vec::new(); - - // for mut file in files { - // let path = &file.path; - - // file.parsed_permissions = if let Some(permissions) = &file.permissions { - // Some(u32::from_str_radix(permissions, 8).with_context(|| { - // format!( - // "Invalid permission string for file {path}: {permissions} (invalid octal)" - // ) - // })?) - // } else { - // None - // }; - - // let contents = std::fs::read(&file.source_path) - // .with_context(|| format!("Failed to read file {}", file.source_path))?; - // file.hash_hex = hex::encode( - // Hash::from_data(HashType::Sha384, &contents) - // .with_context(|| format!("Failed to hash file {}", file.source_path))? - // .value_bytes(), - // ); - // file.contents_len = contents.len(); - // file.contents_hex = hex::encode(&contents); - - // new_files.push(file); - // } - - // Some(new_files) - // } else { - // None - // }; + Some(new_files) + } else { + None + }; Ok(ServiceInfoConfiguration { settings }) } } -// fn check_file_configuration(mut files_to_check: Option>) -> Result> { -fn check_file_configuration(mut files_to_check: Option>) -> Result>> { - files_to_check = if let Some(files) = files_to_check { - let mut new_files = Vec::new(); - - for mut file in files { - let path = &file.path; - - file.parsed_permissions = if let Some(permissions) = &file.permissions { - Some(u32::from_str_radix(permissions, 8).with_context(|| { - format!( - "Invalid permission string for file {path}: {permissions} (invalid octal)" - ) - })?) - } else { - None - }; - - let contents = std::fs::read(&file.source_path) - .with_context(|| format!("Failed to read file {}", file.source_path))?; - file.hash_hex = hex::encode( - Hash::from_data(HashType::Sha384, &contents) - .with_context(|| format!("Failed to hash file {}", file.source_path))? - .value_bytes(), - ); - file.contents_len = contents.len(); - file.contents_hex = hex::encode(&contents); - - new_files.push(file); - } +// impl ServiceInfoConfiguration { +// fn from_settings(settings: ServiceInfoSettings) -> Result { +// // Perform checks on the configuration - Some(new_files) - } else { - None - }; - Ok( files_to_check ) -} +// // Check permissions for files are valid + +// //// TODO: do something with result? +// let _ = check_file_configuration(settings.files.clone()); + +// Ok(ServiceInfoConfiguration { settings }) +// } +// } + +// fn check_file_configuration(mut files_to_check: Option>) -> Result> { +// fn check_file_configuration(mut files_to_check: Option>) -> Result>> { +// files_to_check = if let Some(files) = files_to_check { +// let mut new_files = Vec::new(); + +// for mut file in files { +// let path = &file.path; + +// file.parsed_permissions = if let Some(permissions) = &file.permissions { +// Some(u32::from_str_radix(permissions, 8).with_context(|| { +// format!( +// "Invalid permission string for file {path}: {permissions} (invalid octal)" +// ) +// })?) +// } else { +// None +// }; + +// let contents = std::fs::read(&file.source_path) +// .with_context(|| format!("Failed to read file {}", file.source_path))?; +// file.hash_hex = hex::encode( +// Hash::from_data(HashType::Sha384, &contents) +// .with_context(|| format!("Failed to hash file {}", file.source_path))? +// .value_bytes(), +// ); +// file.contents_len = contents.len(); +// file.contents_hex = hex::encode(&contents); + +// new_files.push(file); +// } + +// Some(new_files) +// } else { +// None +// }; +// Ok( files_to_check ) +// } #[derive(Debug, Clone, Copy)] #[non_exhaustive] @@ -337,11 +346,11 @@ async fn serviceinfo_handler( // precedence is given to 'per_device' settings over base serviceinfo_api_server.yml config match settings_per_device(&query_info.device_guid.to_string().replace('\"', "")) { Ok(config) => { - let per_device_settings = config.clone(); - let per_device_settings1 = config; + let per_device_settings = config; // TODO: do something with result? - let _ = check_file_configuration(per_device_settings1.files); + // let per_device_settings1 = config; + // let _ = check_file_configuration(per_device_settings1.files); if let Some(files) = &per_device_settings.files { // Adding per device files config From 2e3b8c27b17cec8b345c25dae3475a67bb77c15a Mon Sep 17 00:00:00 2001 From: RZandvoort-VSM Date: Mon, 12 Feb 2024 11:22:20 +0100 Subject: [PATCH 11/21] To working state? --- serviceinfo-api-server/src/main.rs | 83 +++++++++++++++--------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/serviceinfo-api-server/src/main.rs b/serviceinfo-api-server/src/main.rs index 1dc26bc63..af39a5a49 100644 --- a/serviceinfo-api-server/src/main.rs +++ b/serviceinfo-api-server/src/main.rs @@ -38,6 +38,7 @@ impl ServiceInfoConfiguration { for mut file in files { let path = &file.path; + // file.parsed_permissions = if let Some(permissions) = &file.permissions { Some(u32::from_str_radix(permissions, 8).with_context(|| { @@ -344,47 +345,47 @@ async fn serviceinfo_handler( } // precedence is given to 'per_device' settings over base serviceinfo_api_server.yml config - match settings_per_device(&query_info.device_guid.to_string().replace('\"', "")) { - Ok(config) => { - let per_device_settings = config; - - // TODO: do something with result? - // let per_device_settings1 = config; - // let _ = check_file_configuration(per_device_settings1.files); - - if let Some(files) = &per_device_settings.files { - // Adding per device files config - for file in files { - reply.add_extra(FedoraIotServiceInfoModule::BinaryFile, "name", &file.path); - reply.add_extra( - FedoraIotServiceInfoModule::BinaryFile, - "length", - &file.contents_len, - ); - if let Some(parsed_permissions) = &file.parsed_permissions { - reply.add_extra( - FedoraIotServiceInfoModule::BinaryFile, - "mode", - &parsed_permissions, - ); - } - reply.add_extra( - FedoraIotServiceInfoModule::BinaryFile, - "data001|hex", - &file.contents_hex, - ); - reply.add_extra( - FedoraIotServiceInfoModule::BinaryFile, - "sha-384|hex", - &file.hash_hex, - ); - } - } - } - Err(_) => { - log::info!("per-device settings file not available, so loading base config file"); - } - }; + // match settings_per_device(&query_info.device_guid.to_string().replace('\"', "")) { + // Ok(config) => { + // let per_device_settings = config; + + // // TODO: do something with result? + // // let per_device_settings1 = config; + // // let _ = check_file_configuration(per_device_settings1.files); + + // if let Some(files) = &per_device_settings.files { + // // Adding per device files config + // for file in files { + // reply.add_extra(FedoraIotServiceInfoModule::BinaryFile, "name", &file.path); + // reply.add_extra( + // FedoraIotServiceInfoModule::BinaryFile, + // "length", + // &file.contents_len, + // ); + // if let Some(parsed_permissions) = &file.parsed_permissions { + // reply.add_extra( + // FedoraIotServiceInfoModule::BinaryFile, + // "mode", + // &parsed_permissions, + // ); + // } + // reply.add_extra( + // FedoraIotServiceInfoModule::BinaryFile, + // "data001|hex", + // &file.contents_hex, + // ); + // reply.add_extra( + // FedoraIotServiceInfoModule::BinaryFile, + // "sha-384|hex", + // &file.hash_hex, + // ); + // } + // } + // } + // Err(_) => { + // log::info!("per-device settings file not available, so loading base config file"); + // } + // }; } if query_info From fe983dfb9aa33bffbeef10d7d27e22bd461bb3b1 Mon Sep 17 00:00:00 2001 From: RZandvoort-VSM Date: Mon, 12 Feb 2024 11:42:28 +0100 Subject: [PATCH 12/21] Add per device files --- serviceinfo-api-server/src/main.rs | 82 +++++++++++++++--------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/serviceinfo-api-server/src/main.rs b/serviceinfo-api-server/src/main.rs index af39a5a49..46794b8d8 100644 --- a/serviceinfo-api-server/src/main.rs +++ b/serviceinfo-api-server/src/main.rs @@ -345,47 +345,47 @@ async fn serviceinfo_handler( } // precedence is given to 'per_device' settings over base serviceinfo_api_server.yml config - // match settings_per_device(&query_info.device_guid.to_string().replace('\"', "")) { - // Ok(config) => { - // let per_device_settings = config; - - // // TODO: do something with result? - // // let per_device_settings1 = config; - // // let _ = check_file_configuration(per_device_settings1.files); - - // if let Some(files) = &per_device_settings.files { - // // Adding per device files config - // for file in files { - // reply.add_extra(FedoraIotServiceInfoModule::BinaryFile, "name", &file.path); - // reply.add_extra( - // FedoraIotServiceInfoModule::BinaryFile, - // "length", - // &file.contents_len, - // ); - // if let Some(parsed_permissions) = &file.parsed_permissions { - // reply.add_extra( - // FedoraIotServiceInfoModule::BinaryFile, - // "mode", - // &parsed_permissions, - // ); - // } - // reply.add_extra( - // FedoraIotServiceInfoModule::BinaryFile, - // "data001|hex", - // &file.contents_hex, - // ); - // reply.add_extra( - // FedoraIotServiceInfoModule::BinaryFile, - // "sha-384|hex", - // &file.hash_hex, - // ); - // } - // } - // } - // Err(_) => { - // log::info!("per-device settings file not available, so loading base config file"); - // } - // }; + match settings_per_device(&query_info.device_guid.to_string().replace('\"', "")) { + Ok(config) => { + let per_device_settings = config; + + // TODO: do something with result? + // let per_device_settings1 = config; + // let _ = check_file_configuration(per_device_settings1.files); + + if let Some(files) = &per_device_settings.files { + // Adding per device files config + for file in files { + reply.add_extra(FedoraIotServiceInfoModule::BinaryFile, "name", &file.path); + reply.add_extra( + FedoraIotServiceInfoModule::BinaryFile, + "length", + &file.contents_len, + ); + if let Some(parsed_permissions) = &file.parsed_permissions { + reply.add_extra( + FedoraIotServiceInfoModule::BinaryFile, + "mode", + &parsed_permissions, + ); + } + reply.add_extra( + FedoraIotServiceInfoModule::BinaryFile, + "data001|hex", + &file.contents_hex, + ); + reply.add_extra( + FedoraIotServiceInfoModule::BinaryFile, + "sha-384|hex", + &file.hash_hex, + ); + } + } + } + Err(_) => { + log::info!("per-device settings file not available, so loading base config file"); + } + }; } if query_info From 3d1631cffd4f60905f58bf7c422f8cc1e98b9bd8 Mon Sep 17 00:00:00 2001 From: Rutger Zandvoort Date: Wed, 14 Feb 2024 10:40:15 +0100 Subject: [PATCH 13/21] Add per-device file implementation --- HOWTO.md | 13 ++ .../config/device_specific_serviceinfo.yml | 5 +- serviceinfo-api-server/src/main.rs | 137 ++++++++++++++---- util/src/servers/mod.rs | 5 +- 4 files changed, 132 insertions(+), 28 deletions(-) diff --git a/HOWTO.md b/HOWTO.md index 890765f41..6c2cfa8de 100644 --- a/HOWTO.md +++ b/HOWTO.md @@ -965,9 +965,18 @@ still required to be set by the user (`DI_SIGN_KEY_PATH`, `DI_HMAC_KEY_PATH`). If other devices do not have their `per-device serviceinfo` file under `device_specific_store_driver` they will get onboarded with settings from the main file, which is `serviceinfo-api-server.yml`. + Where: + - `initial_user`: the initial user from the per-device serviceinfo configuration will be chosen over the base serviceinfo configuration, if exists. + - `files`: add additional [files](#per-device-files) to be written next to the base files. + - `commands`: unhandled + - `diskencryption_clevis`: unhandled + - `additional_serviceinfo`: unhandled + - `after_onboarding_reboot`: unhandled + 1. Initialize the device as mentioned in [How to generate an Ownership Voucher and Credential for a Device](#how-to-generate-an-ownership-voucher-ov-and-credential-for-a-device-device-initialization). 2. Dump the `device-credentials` + ```bash fdo-owner-tool dump-device-credential /path/to/device-credentials ``` @@ -977,3 +986,7 @@ still required to be set by the user (`DI_SIGN_KEY_PATH`, `DI_HMAC_KEY_PATH`). 4. You can refer to [per_device_serviceinfo.yml](https://github.com/fedora-iot/fido-device-onboard-rs/blob/main/examples/config/device_specific_serviceinfo.yml) as an example. 5. Follow the onboarding procedure and this particular device will get the serviceinfo settings as mentioned in the above file. + +#### Per device files + +Files will be written to the `path` location. Both the files from the base and per-device serviceinfo configuration will be written. If the same `path` is defined multiple times in a configuration, the latest `path` definition will be written. If the same `path` is defined in the base as well in the per-device serviceinfo configuration, the per device serviceinfo configuration will have precedence over the base serviceinfo configuration. diff --git a/examples/config/device_specific_serviceinfo.yml b/examples/config/device_specific_serviceinfo.yml index d6de355d5..d89e9b4b9 100755 --- a/examples/config/device_specific_serviceinfo.yml +++ b/examples/config/device_specific_serviceinfo.yml @@ -2,7 +2,10 @@ initial_user: username: username_per_device sshkeys: - "testkeyperdevice" -files: null +files: +- path: /var/lib/fdo/service-info-api/files/hosts + permissions: 644 + source_path: /server/local/etc/hosts commands: null diskencryption_clevis: null additional_serviceinfo: null diff --git a/serviceinfo-api-server/src/main.rs b/serviceinfo-api-server/src/main.rs index ec0dc6f64..a5848b0bc 100644 --- a/serviceinfo-api-server/src/main.rs +++ b/serviceinfo-api-server/src/main.rs @@ -23,6 +23,11 @@ struct ServiceInfoConfiguration { settings: ServiceInfoSettings, } +// #[derive(Debug)] +// struct ServiceInfoFiles { +// files: Vec, +// } + impl ServiceInfoConfiguration { fn from_settings(mut settings: ServiceInfoSettings) -> Result { // Perform checks on the configuration @@ -66,6 +71,57 @@ impl ServiceInfoConfiguration { } } +// impl ServiceInfoConfiguration { +// fn from_settings(settings: ServiceInfoSettings) -> Result { +// // Perform checks on the configuration + +// // Check permissions for files are valid + +// //// TODO: do something with result? +// let _ = check_file_configuration(settings.files.clone()); + +// Ok(ServiceInfoConfiguration { settings }) +// } +// } + +// fn check_file_configuration(mut files_to_check: Option>) -> Result> { +// fn check_file_configuration(mut files_to_check: Option>) -> Result>> { +// files_to_check = if let Some(files) = files_to_check { +// let mut new_files = Vec::new(); + +// for mut file in files { +// let path = &file.path; + +// file.parsed_permissions = if let Some(permissions) = &file.permissions { +// Some(u32::from_str_radix(permissions, 8).with_context(|| { +// format!( +// "Invalid permission string for file {path}: {permissions} (invalid octal)" +// ) +// })?) +// } else { +// None +// }; + +// let contents = std::fs::read(&file.source_path) +// .with_context(|| format!("Failed to read file {}", file.source_path))?; +// file.hash_hex = hex::encode( +// Hash::from_data(HashType::Sha384, &contents) +// .with_context(|| format!("Failed to hash file {}", file.source_path))? +// .value_bytes(), +// ); +// file.contents_len = contents.len(); +// file.contents_hex = hex::encode(&contents); + +// new_files.push(file); +// } + +// Some(new_files) +// } else { +// None +// }; +// Ok( files_to_check ) +// } + #[derive(Debug, Clone, Copy)] #[non_exhaustive] enum ServiceInfoMetadataKey {} @@ -260,32 +316,35 @@ async fn serviceinfo_handler( .contains(&FedoraIotServiceInfoModule::BinaryFile.into()) { if let Some(files) = &user_data.service_info_configuration.settings.files { - for file in files { - reply.add_extra(FedoraIotServiceInfoModule::BinaryFile, "name", &file.path); - reply.add_extra( - FedoraIotServiceInfoModule::BinaryFile, - "length", - &file.contents_len, - ); - if let Some(parsed_permissions) = &file.parsed_permissions { - reply.add_extra( - FedoraIotServiceInfoModule::BinaryFile, - "mode", - &parsed_permissions, - ); - } - reply.add_extra( - FedoraIotServiceInfoModule::BinaryFile, - "data001|hex", - &file.contents_hex, - ); - reply.add_extra( - FedoraIotServiceInfoModule::BinaryFile, - "sha-384|hex", - &file.hash_hex, - ); - } + add_binary_files_to_reply(files, &mut reply); + + log::debug!("Applied base file configuration binary files"); } + + // precedence is given to 'per_device' settings over base serviceinfo_api_server.yml config + match settings_per_device(&query_info.device_guid.to_string().replace('\"', "")) { + Ok(config) => { + log::info!("Per-device file configuration found"); + + let per_device_settings = config; + + match ServiceInfoConfiguration::from_settings(per_device_settings){ + Ok(per_device_service_info_configuration) => { + if let Some(files) = &per_device_service_info_configuration.settings.files { + add_binary_files_to_reply(files, &mut reply); + + log::debug!("Applied per-device file configuration binary files"); + } + } + Err(e) => { + log::error!("{}", e); + } + }; + } + Err(_) => { + log::info!("No per-device settings file configuration found"); + } + }; } if query_info @@ -390,6 +449,34 @@ async fn serviceinfo_handler( Ok(warp::reply::json(&reply.reply)) } +fn add_binary_files_to_reply(files: &Vec, reply: &mut ServiceInfoApiReplyBuilder) { + for file in files { + reply.add_extra(FedoraIotServiceInfoModule::BinaryFile, "name", &file.path); + reply.add_extra( + FedoraIotServiceInfoModule::BinaryFile, + "length", + &file.contents_len, + ); + if let Some(parsed_permissions) = &file.parsed_permissions { + reply.add_extra( + FedoraIotServiceInfoModule::BinaryFile, + "mode", + &parsed_permissions, + ); + } + reply.add_extra( + FedoraIotServiceInfoModule::BinaryFile, + "data001|hex", + &file.contents_hex, + ); + reply.add_extra( + FedoraIotServiceInfoModule::BinaryFile, + "sha-384|hex", + &file.hash_hex, + ); + } +} + fn deserialize_from_str<'de, D>(deserializer: D) -> Result where D: serde::de::Deserializer<'de>, diff --git a/util/src/servers/mod.rs b/util/src/servers/mod.rs index 8805238b8..cd7ef3b39 100644 --- a/util/src/servers/mod.rs +++ b/util/src/servers/mod.rs @@ -90,7 +90,7 @@ pub fn settings_per_device(guid: &str) -> Result { log::debug!("Loaded device specific config from {path_per_device_store}"); let per_device_settings = config.try_deserialize::()?; log::debug!( - "device specific serviceinfosettings: initial_user: {:#?} username: {:#?} sshkeys {:#?}", + "device specific serviceinfosettings: initial_user: {:#?} username: {:#?} sshkeys {:#?} files {:#?}", per_device_settings.initial_user, per_device_settings .initial_user @@ -99,7 +99,8 @@ pub fn settings_per_device(guid: &str) -> Result { per_device_settings .initial_user .as_ref() - .map(|user| &user.sshkeys) + .map(|user| &user.sshkeys), + per_device_settings.files ); Ok(per_device_settings) } From e2f7f41b09d6382201893f78f5891d1c5d9e6564 Mon Sep 17 00:00:00 2001 From: Rutger Zandvoort Date: Wed, 14 Feb 2024 11:21:07 +0100 Subject: [PATCH 14/21] Removed commented code --- serviceinfo-api-server/src/main.rs | 56 ------------------------------ 1 file changed, 56 deletions(-) diff --git a/serviceinfo-api-server/src/main.rs b/serviceinfo-api-server/src/main.rs index a5848b0bc..4d91ca88d 100644 --- a/serviceinfo-api-server/src/main.rs +++ b/serviceinfo-api-server/src/main.rs @@ -23,11 +23,6 @@ struct ServiceInfoConfiguration { settings: ServiceInfoSettings, } -// #[derive(Debug)] -// struct ServiceInfoFiles { -// files: Vec, -// } - impl ServiceInfoConfiguration { fn from_settings(mut settings: ServiceInfoSettings) -> Result { // Perform checks on the configuration @@ -71,57 +66,6 @@ impl ServiceInfoConfiguration { } } -// impl ServiceInfoConfiguration { -// fn from_settings(settings: ServiceInfoSettings) -> Result { -// // Perform checks on the configuration - -// // Check permissions for files are valid - -// //// TODO: do something with result? -// let _ = check_file_configuration(settings.files.clone()); - -// Ok(ServiceInfoConfiguration { settings }) -// } -// } - -// fn check_file_configuration(mut files_to_check: Option>) -> Result> { -// fn check_file_configuration(mut files_to_check: Option>) -> Result>> { -// files_to_check = if let Some(files) = files_to_check { -// let mut new_files = Vec::new(); - -// for mut file in files { -// let path = &file.path; - -// file.parsed_permissions = if let Some(permissions) = &file.permissions { -// Some(u32::from_str_radix(permissions, 8).with_context(|| { -// format!( -// "Invalid permission string for file {path}: {permissions} (invalid octal)" -// ) -// })?) -// } else { -// None -// }; - -// let contents = std::fs::read(&file.source_path) -// .with_context(|| format!("Failed to read file {}", file.source_path))?; -// file.hash_hex = hex::encode( -// Hash::from_data(HashType::Sha384, &contents) -// .with_context(|| format!("Failed to hash file {}", file.source_path))? -// .value_bytes(), -// ); -// file.contents_len = contents.len(); -// file.contents_hex = hex::encode(&contents); - -// new_files.push(file); -// } - -// Some(new_files) -// } else { -// None -// }; -// Ok( files_to_check ) -// } - #[derive(Debug, Clone, Copy)] #[non_exhaustive] enum ServiceInfoMetadataKey {} From d158ff36a17b048b7e40a795f57228314060eca2 Mon Sep 17 00:00:00 2001 From: RZandvoort <25634703+RZandvoort@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:37:25 +0100 Subject: [PATCH 15/21] Update cd.yml --- .github/workflows/cd.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 48a964fac..3cd36830d 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,13 +1,4 @@ on: - push: - branches: - - main - - "*.*.x" - tags: - - v* - schedule: - - cron: '0 0 * * *' - name: Continuous Delivery jobs: From 38d450e16b8959b9af9f20cc9c02b5233641bd7a Mon Sep 17 00:00:00 2001 From: Rutger Zandvoort Date: Sun, 24 Mar 2024 18:01:25 +0100 Subject: [PATCH 16/21] - --- .github/workflows/cd.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 3cd36830d..48a964fac 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,4 +1,13 @@ on: + push: + branches: + - main + - "*.*.x" + tags: + - v* + schedule: + - cron: '0 0 * * *' + name: Continuous Delivery jobs: From aa1e5ccc150265b2d98ac6ae128e956d169993fd Mon Sep 17 00:00:00 2001 From: Rutger Zandvoort Date: Wed, 2 Oct 2024 10:57:55 +0200 Subject: [PATCH 17/21] Add per device commands --- serviceinfo-api-server/src/main.rs | 86 +++++++++++++++++++----------- util/src/servers/mod.rs | 5 +- 2 files changed, 59 insertions(+), 32 deletions(-) diff --git a/serviceinfo-api-server/src/main.rs b/serviceinfo-api-server/src/main.rs index a1e34e77b..7779c4c85 100644 --- a/serviceinfo-api-server/src/main.rs +++ b/serviceinfo-api-server/src/main.rs @@ -263,22 +263,19 @@ async fn serviceinfo_handler( if let Some(files) = &user_data.service_info_configuration.settings.files { add_binary_files_to_reply(files, &mut reply); - log::debug!("Applied base file configuration binary files"); + log::debug!("Added base configuration binary files"); } // precedence is given to 'per_device' settings over base serviceinfo_api_server.yml config match settings_per_device(&query_info.device_guid.to_string().replace('\"', "")) { Ok(config) => { - log::info!("Per-device file configuration found"); - let per_device_settings = config; - match ServiceInfoConfiguration::from_settings(per_device_settings){ Ok(per_device_service_info_configuration) => { if let Some(files) = &per_device_service_info_configuration.settings.files { add_binary_files_to_reply(files, &mut reply); - log::debug!("Applied per-device file configuration binary files"); + log::debug!("Added per-device configuration binary files"); } } Err(e) => { @@ -287,7 +284,7 @@ async fn serviceinfo_handler( }; } Err(_) => { - log::info!("No per-device settings file configuration found"); + log::info!("No per-device configuration file found"); } }; } @@ -296,32 +293,34 @@ async fn serviceinfo_handler( .modules .contains(&FedoraIotServiceInfoModule::Command.into()) { + // Add base configuration commands if let Some(commands) = &user_data.service_info_configuration.settings.commands { - for command in commands { - reply.add_extra( - FedoraIotServiceInfoModule::Command, - "command", - &command.command, - ); - reply.add_extra(FedoraIotServiceInfoModule::Command, "args", &command.args); - reply.add_extra( - FedoraIotServiceInfoModule::Command, - "may_fail", - &command.may_fail, - ); - reply.add_extra( - FedoraIotServiceInfoModule::Command, - "return_stdout", - &command.return_stdout, - ); - reply.add_extra( - FedoraIotServiceInfoModule::Command, - "return_stderr", - &command.return_stderr, - ); - reply.add_extra(FedoraIotServiceInfoModule::Command, "execute", &true); - } + add_commands_to_reply(commands, &mut reply); + + log::debug!("Added base configuration commands"); } + + // Add device specific commands to reply + match settings_per_device(&query_info.device_guid.to_string().replace('\"', "")) { + Ok(config) => { + let per_device_settings = config; + match ServiceInfoConfiguration::from_settings(per_device_settings){ + Ok(per_device_service_info_configuration) => { + if let Some(commands) = &per_device_service_info_configuration.settings.commands { + add_commands_to_reply(commands, &mut reply); + + log::debug!("Added per-device configuration commands"); + } + } + Err(e) => { + log::error!("{}", e); + } + }; + } + Err(_) => { + log::info!("No per-device configuration file found"); + } + }; } if query_info @@ -422,6 +421,33 @@ fn add_binary_files_to_reply(files: &Vec, reply: &mut ServiceInfoApiReplyBuilder) { + for command in commands { + reply.add_extra( + FedoraIotServiceInfoModule::Command, + "command", + &command.command, + ); + reply.add_extra(FedoraIotServiceInfoModule::Command, "args", &command.args); + reply.add_extra( + FedoraIotServiceInfoModule::Command, + "may_fail", + &command.may_fail, + ); + reply.add_extra( + FedoraIotServiceInfoModule::Command, + "return_stdout", + &command.return_stdout, + ); + reply.add_extra( + FedoraIotServiceInfoModule::Command, + "return_stderr", + &command.return_stderr, + ); + reply.add_extra(FedoraIotServiceInfoModule::Command, "execute", &true); + } +} + fn deserialize_from_str<'de, D>(deserializer: D) -> Result where D: serde::de::Deserializer<'de>, diff --git a/util/src/servers/mod.rs b/util/src/servers/mod.rs index 55c634173..6dc9b630b 100644 --- a/util/src/servers/mod.rs +++ b/util/src/servers/mod.rs @@ -90,7 +90,7 @@ pub fn settings_per_device(guid: &str) -> Result { log::debug!("Loaded device specific config from {path_per_device_store}"); let per_device_settings = config.try_deserialize::()?; log::debug!( - "device specific serviceinfosettings: initial_user: {:#?} username: {:#?} sshkeys {:#?} files {:#?}", + "device specific serviceinfosettings: initial_user: {:#?} username: {:#?} sshkeys {:#?} files {:#?} commands {:#?}", per_device_settings.initial_user, per_device_settings .initial_user @@ -100,7 +100,8 @@ pub fn settings_per_device(guid: &str) -> Result { .initial_user .as_ref() .map(|user| &user.sshkeys), - per_device_settings.files + per_device_settings.files, + per_device_settings.commands ); Ok(per_device_settings) } From cd93f422dd6d10115ddf35994ccd10648e59055b Mon Sep 17 00:00:00 2001 From: Rutger Zandvoort Date: Wed, 2 Oct 2024 10:58:06 +0200 Subject: [PATCH 18/21] Update example config --- examples/config/device_specific_serviceinfo.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/examples/config/device_specific_serviceinfo.yml b/examples/config/device_specific_serviceinfo.yml index d89e9b4b9..e1d6d4501 100755 --- a/examples/config/device_specific_serviceinfo.yml +++ b/examples/config/device_specific_serviceinfo.yml @@ -6,7 +6,21 @@ files: - path: /var/lib/fdo/service-info-api/files/hosts permissions: 644 source_path: /server/local/etc/hosts -commands: null +commands: +- command: ls + args: + - /etc/hosts + return_stdout: true + return_stderr: true +- command: ls + args: + - /etc/doesnotexist/whatever.foo + may_fail: true + return_stdout: true + return_stderr: true +- command: touch + args: + - /etc/command-testfile diskencryption_clevis: null additional_serviceinfo: null after_onboarding_reboot: false From 4283016ea09845f232201312e14ffe00240596c4 Mon Sep 17 00:00:00 2001 From: Rutger Zandvoort Date: Wed, 2 Oct 2024 10:58:15 +0200 Subject: [PATCH 19/21] Update HOWTO.md --- HOWTO.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HOWTO.md b/HOWTO.md index d244974ad..c8d7d205c 100644 --- a/HOWTO.md +++ b/HOWTO.md @@ -970,7 +970,7 @@ still required to be set by the user (`DI_SIGN_KEY_PATH`, `DI_HMAC_KEY_PATH`). Where: - `initial_user`: the initial user from the per-device serviceinfo configuration will be chosen over the base serviceinfo configuration, if exists. - `files`: add additional [files](#per-device-files) to be written next to the base files. - - `commands`: unhandled + - `commands`: add additional commands to be executed after the base commands. - `diskencryption_clevis`: unhandled - `additional_serviceinfo`: unhandled - `after_onboarding_reboot`: unhandled From 1d13963883fca604077797a19137cae80d7ec603 Mon Sep 17 00:00:00 2001 From: Rutger Zandvoort Date: Wed, 2 Oct 2024 10:58:19 +0200 Subject: [PATCH 20/21] Clean-up --- .github/workflows/cd.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 48a964fac..3cd36830d 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,13 +1,4 @@ on: - push: - branches: - - main - - "*.*.x" - tags: - - v* - schedule: - - cron: '0 0 * * *' - name: Continuous Delivery jobs: From 70b77b86ef2aa55248aecdb64d1c64505f33e7d5 Mon Sep 17 00:00:00 2001 From: Rutger Zandvoort Date: Wed, 2 Oct 2024 11:06:08 +0200 Subject: [PATCH 21/21] Revert "Clean-up" This reverts commit 1d13963883fca604077797a19137cae80d7ec603. --- .github/workflows/cd.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 3cd36830d..48a964fac 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,4 +1,13 @@ on: + push: + branches: + - main + - "*.*.x" + tags: + - v* + schedule: + - cron: '0 0 * * *' + name: Continuous Delivery jobs: