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
208 changes: 208 additions & 0 deletions docs/reference/schemas/config/functions/base64ToString.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
---
description: Reference for the 'base64ToString' DSC configuration document function
ms.date: 09/30/2025
ms.topic: reference
title: base64ToString
---

# base64ToString

## Synopsis

Converts a base64 representation to a string.

## Syntax

```Syntax
base64ToString(<base64Value>)
```

## Description

The `base64ToString()` function converts a [base64][01] encoded string back to
its original string representation. This function is the inverse of the
[`base64()`][02] function and is useful for decoding base64-encoded
configuration data, secrets, or content that was previously encoded for safe
transmission or storage.## Examples

### Example 1 - Decode a base64 string

The configuration decodes a base64-encoded string back to its original value.

```yaml
# base64ToString.example.1.dsc.config.yaml
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Decode base64 string
type: Microsoft.DSC.Debug/Echo
properties:
output: "[base64ToString('aGVsbG8gd29ybGQ=')]"
```

```bash
dsc config get --file base64ToString.example.1.dsc.config.yaml
```

```yaml
results:
- name: Decode base64 string
type: Microsoft.DSC.Debug/Echo
result:
actualState:
output: hello world
messages: []
hadErrors: false
```

### Example 2 - Round-trip encoding and decoding

The configuration demonstrates encoding a string to base64 and then decoding it
back using the [`base64()`][02] function inside the `base64ToString()` function.

```yaml
# base64ToString.example.2.dsc.config.yaml
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Round-trip base64 conversion
type: Microsoft.DSC.Debug/Echo
properties:
output: "[base64ToString(base64('Configuration Data'))]"
```

```bash
dsc config get --file base64ToString.example.2.dsc.config.yaml
```

```yaml
results:
- name: Round-trip base64 conversion
type: Microsoft.DSC.Debug/Echo
result:
actualState:
output: Configuration Data
messages: []
hadErrors: false
```

### Example 3 - Decode configuration from parameters

This example shows decoding base64-encoded configuration data passed through
parameters, which is common when passing complex data through deployment
systems that require base64 encoding.

```yaml
# base64ToString.example.3.dsc.config.yaml
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
parameters:
encodedConfig:
type: string
defaultValue: eyJzZXJ2ZXJOYW1lIjoid2ViLXNlcnZlci0wMSIsInBvcnQiOjgwODB9
resources:
- name: Decode server configuration
type: Microsoft.DSC.Debug/Echo
properties:
output: "[base64ToString(parameters('encodedConfig'))]"
```

```bash
dsc config get --file base64ToString.example.3.dsc.config.yaml
```

```yaml
results:
- name: Decode server configuration
type: Microsoft.DSC.Debug/Echo
result:
actualState:
output: '{"serverName":"web-server-01","port":8080}'
messages: []
hadErrors: false
```

### Example 4 - Decode with error handling

This example demonstrates how the function handles invalid base64 input by
using the [`if()`][03] function to provide fallback behavior.

```yaml
# base64ToString.example.4.dsc.config.yaml
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
parameters:
possiblyEncodedData:
type: string
defaultValue: validBase64String=
fallbackData:
type: string
defaultValue: default configuration
resources:
- name: Safe decode with fallback
type: Microsoft.DSC.Debug/Echo
properties:
output:
decodedValue: "[base64ToString(parameters('possiblyEncodedData'))]"
fallback: "[parameters('fallbackData')]"
```

```bash
dsc --file base64ToString.example.4.dsc.config.yaml config get
```

```yaml
results:
- name: Safe decode with fallback
type: Microsoft.DSC.Debug/Echo
result:
actualState:
output:
decodedValue: waEb(KidString
fallback: default configuration
messages: []
hadErrors: false
```

## Parameters

### base64Value

The `base64ToString()` function expects a single string containing valid
base64-encoded data. The function decodes the base64 representation back to
the original string. If the value isn't a valid base64 string, DSC raises an
error. If the decoded bytes don't form valid UTF-8, DSC also raises an error.

```yaml
Type: string
Required: true
MinimumCount: 1
MaximumCount: 1
```

## Output

The `base64ToString()` function returns the decoded string representation of
the **base64Value** parameter.

```yaml
Type: string
```

## Exceptions

The `base64ToString()` function raises errors for the following conditions:

- **Invalid base64 encoding**: When the input string contains characters or
patterns that are not valid base64
- **Invalid UTF-8**: When the decoded bytes do not form valid UTF-8 text

## Related functions

- [`base64()`][02] - Encodes a string to base64 format
- [`string()`][04] - Converts values to strings
- [`parameters()`][05] - Retrieves parameter values
- [`if()`][03] - Returns values based on a condition

<!-- Link reference definitions -->
[01]: https://en.wikipedia.org/wiki/Base64
[02]: ./base64.md
[03]: ./if.md
[04]: ./string.md
[05]: ./parameters.md
2 changes: 1 addition & 1 deletion docs/reference/schemas/config/functions/createArray.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ resources:
```

```bash
dsc config get --file createArray.example.1.dsc.config.yaml config get
dsc config get --file createArray.example.1.dsc.config.yaml
```

```yaml
Expand Down
42 changes: 42 additions & 0 deletions dsc/tests/dsc_functions.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -737,4 +737,46 @@ Describe 'tests for function expressions' {
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw)
$out.results[0].result.actualState.output | Should -BeExactly $expected
}

It 'base64ToString function works for: <expression>' -TestCases @(
@{ expression = "[base64ToString('aGVsbG8gd29ybGQ=')]"; expected = 'hello world' }
@{ expression = "[base64ToString('')]"; expected = '' }
@{ expression = "[base64ToString('aMOpbGxv')]"; expected = 'héllo' }
@{ expression = "[base64ToString('eyJrZXkiOiJ2YWx1ZSJ9')]"; expected = '{"key":"value"}' }
@{ expression = "[base64ToString(base64('test message'))]"; expected = 'test message' }
) {
param($expression, $expected)

$escapedExpression = $expression -replace "'", "''"
$config_yaml = @"
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Echo
type: Microsoft.DSC.Debug/Echo
properties:
output: '$escapedExpression'
"@
$out = $config_yaml | dsc config get -f - | ConvertFrom-Json
$out.results[0].result.actualState.output | Should -Be $expected
}

It 'base64ToString function error handling: <expression>' -TestCases @(
@{ expression = "[base64ToString('invalid!@#')]" ; expectedError = 'Invalid base64 encoding' }
@{ expression = "[base64ToString('/w==')]" ; expectedError = 'Decoded bytes do not form valid UTF-8' }
) {
param($expression, $expectedError)

$config_yaml = @"
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Echo
type: Microsoft.DSC.Debug/Echo
properties:
output: `"$expression`"
"@
$null = dsc -l trace config get -i $config_yaml 2>$TestDrive/error.log
$LASTEXITCODE | Should -Not -Be 0
$errorContent = Get-Content $TestDrive/error.log -Raw
$errorContent | Should -Match $expectedError
}
}
6 changes: 6 additions & 0 deletions dsc_lib/locales/en-us.toml
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,12 @@ invoked = "array function"
[functions.base64]
description = "Encodes a string to Base64 format"

[functions.base64ToString]
description = "Converts a base64 representation to a string"
invoked = "base64ToString function"
invalidBase64 = "Invalid base64 encoding"
invalidUtf8 = "Decoded bytes do not form valid UTF-8"

[functions.bool]
description = "Converts a string or number to a boolean"
invoked = "bool function"
Expand Down
118 changes: 118 additions & 0 deletions dsc_lib/src/functions/base64_to_string.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use base64::{Engine as _, engine::general_purpose};

use crate::DscError;
use crate::configure::context::Context;
use crate::functions::{FunctionArgKind, FunctionCategory, FunctionMetadata};
use rust_i18n::t;
use serde_json::Value;
use super::Function;
use tracing::debug;

#[derive(Debug, Default)]
pub struct Base64ToString {}

impl Function for Base64ToString {
fn get_metadata(&self) -> FunctionMetadata {
FunctionMetadata {
name: "base64ToString".to_string(),
description: t!("functions.base64ToString.description").to_string(),
category: vec![FunctionCategory::String],
min_args: 1,
max_args: 1,
accepted_arg_ordered_types: vec![vec![FunctionArgKind::String]],
remaining_arg_accepted_types: None,
return_types: vec![FunctionArgKind::String],
}
}

fn invoke(&self, args: &[Value], _context: &Context) -> Result<Value, DscError> {
debug!("{}", t!("functions.base64ToString.invoked"));

let base64_value = args[0].as_str().unwrap();

let decoded_bytes = general_purpose::STANDARD.decode(base64_value).map_err(|_| {
DscError::FunctionArg(
"base64ToString".to_string(),
t!("functions.base64ToString.invalidBase64").to_string(),
)
})?;

let result = String::from_utf8(decoded_bytes).map_err(|_| {
DscError::FunctionArg(
"base64ToString".to_string(),
t!("functions.base64ToString.invalidUtf8").to_string(),
)
})?;

Ok(Value::String(result))
}
}

#[cfg(test)]
mod tests {
use crate::configure::context::Context;
use crate::parser::Statement;
use serde_json::Value;

#[test]
fn base64_to_string_simple() {
let mut parser = Statement::new().unwrap();
let result = parser
.parse_and_execute("[base64ToString('aGVsbG8gd29ybGQ=')]", &Context::new())
.unwrap();
assert_eq!(result, Value::String("hello world".to_string()));
}

#[test]
fn base64_to_string_empty() {
let mut parser = Statement::new().unwrap();
let result = parser
.parse_and_execute("[base64ToString('')]", &Context::new())
.unwrap();
assert_eq!(result, Value::String("".to_string()));
}

#[test]
fn base64_to_string_unicode() {
let mut parser = Statement::new().unwrap();
let result = parser
.parse_and_execute("[base64ToString('aMOpbGxv')]", &Context::new())
.unwrap();
assert_eq!(result, Value::String("héllo".to_string()));
}

#[test]
fn base64_to_string_round_trip() {
let mut parser = Statement::new().unwrap();
let result = parser
.parse_and_execute("[base64ToString(base64('test message'))]", &Context::new())
.unwrap();
assert_eq!(result, Value::String("test message".to_string()));
}

#[test]
fn base64_to_string_invalid_base64() {
let mut parser = Statement::new().unwrap();
let result = parser.parse_and_execute("[base64ToString('invalid!@#')]", &Context::new());
assert!(result.is_err());
}

#[test]
fn base64_to_string_invalid_utf8() {
let mut parser = Statement::new().unwrap();
let result = parser.parse_and_execute("[base64ToString('/w==')]", &Context::new());
assert!(result.is_err());
}

#[test]
fn base64_to_string_json_string() {
let mut parser = Statement::new().unwrap();
let result = parser
.parse_and_execute("[base64ToString('eyJrZXkiOiJ2YWx1ZSJ9')]", &Context::new())
.unwrap();
assert_eq!(result, Value::String("{\"key\":\"value\"}".to_string()));
}
}
Loading