Skip to content

Commit d5d2f5d

Browse files
committed
Validate semver of resource manifests
1 parent f2a9b17 commit d5d2f5d

File tree

4 files changed

+68
-2
lines changed

4 files changed

+68
-2
lines changed

dsc/tests/dsc_discovery.tests.ps1

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,45 @@ Describe 'tests for resource discovery' {
6767
$resources = dsc resource list | ConvertFrom-Json
6868
$resources.Count | Should -Be 0
6969
}
70+
71+
It 'warns on invalid semver' {
72+
$manifest = @'
73+
{
74+
"$schema": "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/bundled/resource/manifest.json",
75+
"type": "Test/Echo",
76+
"version": "1.1.0..1",
77+
"get": {
78+
"executable": "dsctest",
79+
"args": [
80+
"echo",
81+
"--input",
82+
"{json}"
83+
],
84+
"input": {
85+
"arg": "{json}"
86+
}
87+
},
88+
"schema": {
89+
"command": {
90+
"executable": "dsctest",
91+
"args": [
92+
"schema",
93+
"-s",
94+
"echo"
95+
]
96+
}
97+
}
98+
}
99+
'@
100+
$oldPath = $env:DSC_RESOURCE_PATH
101+
try {
102+
$env:DSC_RESOURCE_PATH = $testdrive
103+
Set-Content -Path "$testdrive/test.dsc.resource.json" -Value $manifest
104+
$out = dsc resource list 2>&1
105+
$out | Should -Match 'WARN.*?Validation.*?Invalid manifest.*?version'
106+
}
107+
finally {
108+
$env:DSC_RESOURCE_PATH = $oldPath
109+
}
110+
}
70111
}

dsc_lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ serde_json = { version = "1.0", features = ["preserve_order"] }
1818
serde_yaml = { version = "0.9.3" }
1919
thiserror = "1.0"
2020
security_context_lib = { path = "../security_context_lib" }
21+
semver = "1.0"
2122
tracing = "0.1.37"
2223
tracing-indicatif = { version = "0.3.6" }
2324
tree-sitter = "0.22"

dsc_lib/src/discovery/command_discovery.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use crate::discovery::discovery_trait::ResourceDiscovery;
55
use crate::discovery::convert_wildcard_to_regex;
66
use crate::dscresources::dscresource::{Capability, DscResource, ImplementedAs};
7-
use crate::dscresources::resource_manifest::{import_manifest, Kind, ResourceManifest};
7+
use crate::dscresources::resource_manifest::{import_manifest, validate_semver, Kind, ResourceManifest};
88
use crate::dscresources::command_resource::invoke_command;
99
use crate::dscresources::command_resource::log_resource_traces;
1010
use crate::dscerror::DscError;
@@ -380,6 +380,10 @@ fn load_manifest(path: &Path) -> Result<DscResource, DscError> {
380380
}
381381
};
382382

383+
if let Err(err) = validate_semver(&manifest.version) {
384+
return Err(DscError::Validation(format!("Invalid manifest {:?} version value: {err}", path)));
385+
}
386+
383387
let kind = if let Some(kind) = manifest.kind.clone() {
384388
kind
385389
} else if manifest.adapter.is_some() {

dsc_lib/src/dscresources/resource_manifest.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
use schemars::JsonSchema;
5+
use semver::Version;
56
use serde::{Deserialize, Serialize};
67
use serde_json::Value;
78
use std::collections::HashMap;
@@ -28,6 +29,7 @@ pub struct ResourceManifest {
2829
#[serde(skip_serializing_if = "Option::is_none")]
2930
pub kind: Option<Kind>,
3031
/// The version of the resource using semantic versioning.
32+
#[validate(custom(function = "validate_semver"))]
3133
pub version: String,
3234
/// The description of the resource.
3335
pub description: Option<String>,
@@ -232,11 +234,29 @@ pub struct ListMethod {
232234
///
233235
/// * `DscError` - The JSON value is invalid or the schema version is not supported.
234236
pub fn import_manifest(manifest: Value) -> Result<ResourceManifest, DscError> {
237+
// TODO: enable schema version validation, if not provided, use the latest
235238
// const MANIFEST_SCHEMA_VERSION: &str = "https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/bundled/resource/manifest.json";
236239
let manifest = serde_json::from_value::<ResourceManifest>(manifest)?;
237240
// if !manifest.schema_version.eq(MANIFEST_SCHEMA_VERSION) {
238241
// return Err(DscError::InvalidManifestSchemaVersion(manifest.schema_version, MANIFEST_SCHEMA_VERSION.to_string()));
239242
// }
240-
241243
Ok(manifest)
242244
}
245+
246+
/// Validate a semantic version string.
247+
///
248+
/// # Arguments
249+
///
250+
/// * `version` - The semantic version string to validate.
251+
///
252+
/// # Returns
253+
///
254+
/// * `Result<(), ValidationError>` - The result of the validation.
255+
///
256+
/// # Errors
257+
///
258+
/// * `DscError` - The version string is not a valid semantic version.
259+
pub fn validate_semver(version: &str) -> Result<(), semver::Error> {
260+
Version::parse(version)?;
261+
Ok(())
262+
}

0 commit comments

Comments
 (0)