Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,19 @@ Describe 'Tests for the secret() function and extensions' {
$out.results.Count | Should -Be 1
$out.results[0].result.actualState.Output | Should -BeExactly 'SameSecret'
}

It 'Secret with multiple lines' {
$configYaml = @'
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Echo
type: Microsoft.DSC.Debug/Echo
properties:
output: "[secret('MultiLine')]"
'@
dsc -l trace config get -i $configYaml 2> $TestDrive/error.log | ConvertFrom-Json
$LASTEXITCODE | Should -Be 2
$errorMessage = Get-Content -Raw -Path $TestDrive/error.log
$errorMessage | Should -Match "Extension 'Test/Secret2' returned multiple lines which is not supported for secrets"
}
}
3 changes: 1 addition & 2 deletions dsc_lib/locales/en-us.toml
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,12 @@ discoverNoResults = "No results returned for discovery extension '%{extension}'"
discoverNotAbsolutePath = "Resource path from extension '%{extension}' is not an absolute path: %{path}"
extensionReturned = "Extension '%{extension}' returned line: %{line}"
retrievingSecretFromExtension = "Retrieving secret '%{name}' from extension '%{extension}'"
secretExtensionReturnedInvalidJson = "Extension '%{extension}' returned invalid JSON: %{error}"
extensionReturnedSecret = "Extension '%{extension}' returned secret"
extensionReturnedNoSecret = "Extension '%{extension}' did not return a secret"
secretNoResults = "Extension '%{extension}' returned no output"
importingFile = "Importing file '%{file}' with extension '%{extension}'"
importNotSupported = "Import is not supported by extension '%{extension}' for file '%{file}'"
importNoResults = "Extension '%{extension}' returned no results for import"
secretMultipleLinesReturned = "Extension '%{extension}' returned multiple lines which is not supported for secrets"

[extensions.extension_manifest]
extensionManifestSchemaTitle = "Extension manifest schema URI"
Expand Down
36 changes: 23 additions & 13 deletions dsc_lib/src/extensions/dscextension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,20 @@ use schemars::JsonSchema;
use std::{fmt::Display, path::Path};
use tracing::{debug, info, trace};

use crate::{discovery::command_discovery::{load_manifest, ImportedManifest}, dscerror::DscError, dscresources::{command_resource::{invoke_command, process_args}, dscresource::DscResource}, extensions::{import::ImportArgKind, secret::SecretResult}};
use crate::{
discovery::command_discovery::{
load_manifest, ImportedManifest
},
dscerror::DscError,
dscresources::{
command_resource::{
invoke_command,
process_args
},
dscresource::DscResource
},
extensions::import::ImportArgKind
};

use super::{discover::DiscoverResult, extension_manifest::ExtensionManifest, secret::SecretArgKind};

Expand Down Expand Up @@ -229,21 +242,18 @@ impl DscExtension {
extension.exit_codes.as_ref(),
)?;
if stdout.is_empty() {
info!("{}", t!("extensions.dscextension.secretNoResults", extension = self.type_name));
debug!("{}", t!("extensions.dscextension.extensionReturnedNoSecret", extension = self.type_name));
Ok(None)
} else {
let result: SecretResult = match serde_json::from_str(&stdout) {
Ok(value) => value,
Err(err) => {
return Err(DscError::Extension(t!("extensions.dscextension.secretExtensionReturnedInvalidJson", extension = self.type_name, error = err).to_string()));
}
};
if result.secure_string.is_some() {
debug!("{}", t!("extensions.dscextension.extensionReturnedSecret", extension = self.type_name));
// see if multiple lines were returned
let secret = if stdout.lines().count() > 1 {
return Err(DscError::NotSupported(t!("extensions.dscextension.secretMultipleLinesReturned", extension = self.type_name).to_string()));
} else {
debug!("{}", t!("extensions.dscextension.extensionReturnedNoSecret", extension = self.type_name));
}
Ok(result.secure_string)
debug!("{}", t!("extensions.dscextension.extensionReturnedSecret", extension = self.type_name));
// remove any trailing newline characters
stdout.trim_end_matches('\n').to_string()
};
Ok(Some(secret))
}
} else {
Err(DscError::UnsupportedCapability(
Expand Down
6 changes: 0 additions & 6 deletions dsc_lib/src/extensions/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,3 @@ pub struct SecretMethod {
/// The arguments to pass to the command to perform a Get.
pub args: Option<Vec<SecretArgKind>>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
pub struct SecretResult {
#[serde(rename = "secureString")]
pub secure_string: Option<String>,
}
25 changes: 25 additions & 0 deletions examples/extensions/azcli/azcli.dsc.extension.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/extension/manifest.json",
"type": "Microsoft.Azure.CLI/KeyVault",
"version": "1.0.0",
"description": "Retrieve secrets from Azure KeyVault. Requires AzCLI to already be installed.",
"secret": {
"executable": "az.cmd",
"outputKind": "PlainText",
"args": [
"keyvault",
"secret",
"show",
{
"vaultArg": "--vault-name"
},
{
"nameArg": "--name"
},
"--query",
"value",
"--output",
"tsv"
]
}
}
2 changes: 1 addition & 1 deletion extensions/bicep/bicep.dsc.extension.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/extension/manifest.json",
"type": "Microsoft.DSC.Extension/Bicep",
"version": "0.1.0",
"description": "Enable passing Bicep file directly to DSC, but requires bicep executable to be available.",
Expand Down
5 changes: 2 additions & 3 deletions extensions/test/secret/secret.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ $secretTwo = @{
DifferentSecret = 'Hello2'
DuplicateSecret = 'World2'
DuplicateSame = 'SameSecret'
MultiLine = "This`nis`nmultiline"
}
}

Expand All @@ -43,10 +44,8 @@ function get-secret($hashtable, $name, $vault) {
return $null
}

$secret = if ($Second) {
if ($Second) {
get-secret -hashtable $secretTwo -name $Name -vault $Vault
} else {
get-secret -hashtable $secretsOne -name $Name -vault $Vault
}
Comment thread
SteveL-MSFT marked this conversation as resolved.

@{ secureString = $secret } | ConvertTo-Json -Compress | Write-Output
4 changes: 2 additions & 2 deletions extensions/test/secret/testSecret.dsc.extension.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/extension/manifest.json",
"type": "Test/Secret",
"version": "0.1.0",
"description": "Example secret resource for testing.",
"description": "Example secret extension for testing.",
"secret": {
"executable": "pwsh",
"args": [
Expand Down
4 changes: 2 additions & 2 deletions extensions/test/secret/testSecret2.dsc.extension.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/extension/manifest.json",
"type": "Test/Secret2",
"version": "0.1.0",
"description": "Duplicate secret resource for testing.",
"description": "Duplicate secret extension for testing.",
"secret": {
"executable": "pwsh",
"args": [
Expand Down
Loading