Skip to content

Commit

Permalink
Merge pull request #889 from Badgerati/develop
Browse files Browse the repository at this point in the history
v2.5.1
  • Loading branch information
Badgerati committed Dec 21, 2021
2 parents dfff42c + b20621e commit cc45830
Show file tree
Hide file tree
Showing 24 changed files with 114 additions and 35 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ ps_modules/
docs/[Ff]unctions/
examples/state.json
examples/issue-*
examples/issues/
pkg/


Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/powershell:7.1.5-ubuntu-20.04
FROM mcr.microsoft.com/powershell:7.2.1-ubuntu-20.04
LABEL maintainer="Matthew Kelly (Badgerati)"
RUN mkdir -p /usr/local/share/powershell/Modules/Pode
COPY ./pkg/ /usr/local/share/powershell/Modules/Pode
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# <img src="https://github.com/Badgerati/Pode/blob/develop/images/icon.png?raw=true" width="25" /> Pode
# <img src="https://github.com/Badgerati/Pode/blob/develop/images/icon-transparent.png?raw=true" width="30" style="margin-bottom:-5px;margin-right:-3px" /> Pode

[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/Badgerati/Pode/master/LICENSE.txt)
[![Documentation](https://img.shields.io/github/v/release/badgerati/pode?label=docs)](https://badgerati.github.io/Pode)
Expand Down
2 changes: 1 addition & 1 deletion alpine.dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/powershell:7.1.5-alpine-3.13-20211021
FROM mcr.microsoft.com/powershell:7.2.1-alpine-3.14-20211209
LABEL maintainer="Matthew Kelly (Badgerati)"
RUN mkdir -p /usr/local/share/powershell/Modules/Pode
COPY ./pkg/ /usr/local/share/powershell/Modules/Pode
2 changes: 1 addition & 1 deletion arm32.dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/powershell:7.1.5-arm32v7-ubuntu-18.04-20211021
FROM mcr.microsoft.com/powershell:7.2.1-arm32v7-ubuntu-18.04-20211209
LABEL maintainer="Matthew Kelly (Badgerati)"
RUN mkdir -p /usr/local/share/powershell/Modules/Pode
COPY ./pkg/ /usr/local/share/powershell/Modules/Pode
2 changes: 1 addition & 1 deletion docs/Getting-Started/Installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Install-Module -Name Pode
[![Docker](https://img.shields.io/docker/stars/badgerati/pode.svg?label=Stars)](https://hub.docker.com/r/badgerati/pode/)
[![Docker](https://img.shields.io/docker/pulls/badgerati/pode.svg?label=Pulls)](https://hub.docker.com/r/badgerati/pode/)

Pode can run on *nix environments, therefore it only makes sense for there to be Docker images for you to use! The images use PowerShell v7.1.5 on either an Ubuntu Bionic image (default), an Alpine image, or an ARM32 image (for Raspberry Pis).
Pode can run on *nix environments, therefore it only makes sense for there to be Docker images for you to use! The images use PowerShell v7.2.1 on either an Ubuntu Focal image (default), an Alpine image, or an ARM32 image (for Raspberry Pis).

* To pull down the latest Pode image you can do:

Expand Down
4 changes: 2 additions & 2 deletions docs/Hosting/Docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Pode has a Docker image that you can use to host your server, for instructions on pulling these images you can [look here](../../Installation).

The images use PowerShell v7.1.5 on either an Ubuntu Bionic (default), Alpine, or ARM32 image.
The images use PowerShell v7.2.1 on either an Ubuntu Focal (default), Alpine, or ARM32 image.

## Images

Expand All @@ -11,7 +11,7 @@ The images use PowerShell v7.1.5 on either an Ubuntu Bionic (default), Alpine, o

### Default

The default Pode image is an Ubuntu Bionic image with PowerShell v7.1.5 and Pode installed. An example of using this image in your Dockerfile could be as follows:
The default Pode image is an Ubuntu Focal image with PowerShell v7.2.1 and Pode installed. An example of using this image in your Dockerfile could be as follows:

```dockerfile
# pull down the pode image
Expand Down
8 changes: 7 additions & 1 deletion docs/Hosting/IIS.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ Start-PodeServer {
}
```

If the required header is missing, then Pode responds with a 401. The retrieved user, like other authentication, is set on the [web event](../../../WebEvent)'s `$WebEvent.Auth.User` property, and contains the same information as Pode's inbuilt Windows AD authenticator:
If the required header is missing, then Pode responds with a 401. The retrieved user, like other authentication, is set on the [web event](../../Tutorials/WebEvent)'s `$WebEvent.Auth.User` property, and contains the same information as Pode's inbuilt Windows AD authenticator:

| Name | Type | Description |
| ---- | ---- | ----------- |
Expand All @@ -283,6 +283,12 @@ If the required header is missing, then Pode responds with a 401. The retrieved
!!! note
If the authenticated user is a Local User, then the following properties will be empty: FQDN, Email, and DistinguishedName

### Client Certificates

You can enable Pode to get client certificates from IIS by passing `-AllowClientCertificate` to your [`Add-PodeEndpoint`](../../Functions/Core/Add-PodeEndpoint). Pode will check for either the `MS-ASPNETCORE-CLIENTCERT` or `X-ARR-ClientCert` headers, and if either is present they'll be used to set the certificate against `$WebEvent.Request.ClientCertificate`.

This also allows for using [Client Certificate](../../Tutorials/Authentication/Methods/ClientCertificate) authentication in Pode, even when behind IIS.

### Additional Validation

Similar to the normal [`Add-PodeAuth`](../../Functions/Authentication/Add-PodeAuth), [`Add-PodeAuthIIS`](../../Functions/Authentication/Add-PodeAuthIIS) can be supplied can an optional ScriptBlock parameter. This ScriptBlock is supplied the found User object as a parameter, structured as details above. You can then use this to further check the user, or load additional user information from another storage.
Expand Down
2 changes: 1 addition & 1 deletion docs/Tutorials/Authentication/Methods/JWT.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ eyJ0eXAiOiJKV1QiLCJhbGciOiJoczI1NiJ9.eyJleHAiOjE2MjI1NTMyMTQsIm5hbWUiOiJKb2huIER

Pode has a [`ConvertFrom-PodeJwt`](../../../../Functions/Authentication/ConvertFrom-PodeJwt) that can be used to parse a valid JWT. Only the algorithms at the top of this page are supported for verifying the signature. You can skip signature verification by passing `-IgnoreSignature`. On success, the payload of the JWT is returned.

For example, if the created JWT was suplplied:
For example, if the created JWT was supplied:

```powershell
ConvertFrom-PodeJwt -Token 'eyJ0eXAiOiJKV1QiLCJhbGciOiJoczI1NiJ9.eyJleHAiOjE2MjI1NTMyMTQsIm5hbWUiOiJKb2huIERvZSIsInN1YiI6IjEyMyJ9.LP-O8OKwix91a-SZwVK35gEClLZQmsORbW0un2Z4RkY' -Secret 'abc'
Expand Down
Binary file added docs/images/icon-transparent.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Release Notes

## v2.5.1

```plain
### Bugs
* #877: Fix for `ConvertFrom-PodeJwt` expecting string not byte[]
* #879: Fix for retrieving Client Certificates from IIS
* #883: Fix for view engine extensions not being ToLower'd
### Documentation
* #805: Add announcement bar to docs, referencing official docs on GitHub
### Packaging
* #873: Bump PowerShell to v7.2.1 in Docker images
* #881: Bump mkdocs to v1.2.3, and Material theme to v8.1.2
```

## v2.5.0

```plain
Expand Down
4 changes: 2 additions & 2 deletions examples/iis-example.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ Import-Module "$($path)/src/Pode.psm1" -Force -ErrorAction Stop
Start-PodeServer {

# listen on localhost:8085
Add-PodeEndpoint -Address * -Port 8085 -Protocol Http
Add-PodeEndpoint -Address * -Port 8085 -Protocol Http -AllowClientCertificate
New-PodeLoggingMethod -Terminal | Enable-PodeRequestLogging
New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging

Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
Write-PodeJsonResponse -Value @{ Message = 'Hello' }
$WebEvent.Request.Headers | Out-Default
$WebEvent.Request | out-default
}

}
Binary file added images/icon-transparent.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions mkdocs-overrides/main.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% extends "base.html" %}

{% block announce %}
Pode's official documentation is hosted on <a href="https://badgerati.github.io/Pode">GitHub</a>. If you're seeing this elsewhere, like readthedocs, please use the docs on GitHub 😊
{% endblock %}
5 changes: 4 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ site_name: Pode

theme:
name: material
logo: images/icon.png
logo: images/icon-transparent.png
favicon: images/favicon.ico
custom_dir: mkdocs-overrides
features:
- navigation.tabs
- navigation.tabs.sticky
- navigation.tracking
- navigation.top
font:
text: Fira Sans
code: Fira Code
Expand Down
2 changes: 1 addition & 1 deletion packers/docker/arm32/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM arm32v7/ubuntu:bionic

ENV PS_VERSION=7.1.5
ENV PS_VERSION=7.2.1
ENV PS_PACKAGE=powershell-${PS_VERSION}-linux-arm32.tar.gz
ENV PS_PACKAGE_URL=https://github.com/PowerShell/PowerShell/releases/download/v${PS_VERSION}/${PS_PACKAGE}

Expand Down
4 changes: 2 additions & 2 deletions pode.build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ param (

$Versions = @{
Pester = '4.8.0'
MkDocs = '1.1.2'
MkDocs = '1.2.3'
PSCoveralls = '1.0.0'
SevenZip = '18.5.0.20180730'
DotNetCore = '3.1.5'
Checksum = '0.2.0'
MkDocsTheme = '7.1.6'
MkDocsTheme = '8.1.2'
PlatyPS = '0.14.0'
}

Expand Down
6 changes: 4 additions & 2 deletions src/Listener/PodeRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ public class PodeRequest : PodeProtocol, IDisposable
public virtual bool CloseImmediately { get => false; }

public Stream InputStream { get; private set; }
public X509Certificate2 ClientCertificate { get; private set; }
public SslPolicyErrors ClientCertificateErrors { get; private set; }
public bool AllowClientCertificate { get; private set; }
public X509Certificate2 ClientCertificate { get; set; }
public SslPolicyErrors ClientCertificateErrors { get; set; }
public HttpRequestException Error { get; set; }
public bool IsAborted => (Error != default(HttpRequestException));
public bool IsDisposed { get; private set; }
Expand Down Expand Up @@ -58,6 +59,7 @@ public void Open(X509Certificate certificate, SslProtocols protocols, bool allow
{
// ssl or not?
IsSsl = (certificate != default(X509Certificate));
AllowClientCertificate = allowClientCertificate;

// open the socket's stream
InputStream = new NetworkStream(Socket, true);
Expand Down
1 change: 1 addition & 0 deletions src/Pode.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
'Get-PodeLockable',
'Test-PodeLockable',
'Out-PodeVariable',
'Test-PodeIsHosted',

# routes
'Add-PodeRoute',
Expand Down
26 changes: 26 additions & 0 deletions src/Private/Middleware.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using namespace System.Security.Cryptography

function Invoke-PodeMiddleware
{
param (
Expand Down Expand Up @@ -375,6 +377,30 @@ function Initialize-PodeIISMiddleware
return $true
}

# add middleware to check if there's a client cert
Add-PodeMiddleware -Name '__pode_iis_clientcert_check__' -ScriptBlock {
if (!$WebEvent.Request.AllowClientCertificate -or ($null -ne $WebEvent.Request.ClientCertificate)) {
return $true
}

$headers = @('MS-ASPNETCORE-CLIENTCERT', 'X-ARR-ClientCert')
foreach ($header in $headers) {
if (!(Test-PodeHeader -Name $header)) {
continue
}

try {
$value = Get-PodeHeader -Name $header
$WebEvent.Request.ClientCertificate = [X509Certificates.X509Certificate2]::new([Convert]::FromBase64String($value))
}
catch {
$WebEvent.Request.ClientCertificateErrors = [System.Net.Security.SslPolicyErrors]::RemoteCertificateNotAvailable
}
}

return $true
}

# add route to gracefully shutdown server for iis
Add-PodeRoute -Method Post -Path '/iisintegration' -ScriptBlock {
$eventType = Get-PodeHeader -Name 'MS-ASPNETCORE-EVENT'
Expand Down
21 changes: 11 additions & 10 deletions src/Public/Authentication.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,7 @@ A Hashtable containing the Header information for the JWT.
A Hashtable containing the Payload information for the JWT.
.PARAMETER Secret
An Optional Secret for signing the JWT. This is mandatory if the Header algorithm isn't "none".
An Optional Secret for signing the JWT, should be a string or byte[]. This is mandatory if the Header algorithm isn't "none".
.EXAMPLE
ConvertTo-PodeJwt -Header @{ alg = 'none' } -Payload @{ sub = '123'; name = 'John' }
Expand All @@ -1507,8 +1507,7 @@ function ConvertTo-PodeJwt
$Payload,

[Parameter()]
[string]
$Secret
$Secret = $null
)

# validate header
Expand All @@ -1526,13 +1525,12 @@ function ConvertTo-PodeJwt
$jwt = "$($header64).$($payload64)"

# convert secret to bytes
$secretBytes = $null
if (![string]::IsNullOrWhiteSpace($Secret)) {
$secretBytes = [System.Text.Encoding]::UTF8.GetBytes($Secret)
if (($null -ne $Secret) -and ($Secret -isnot [byte[]])) {
$Secret = [System.Text.Encoding]::UTF8.GetBytes([string]$Secret)
}

# make the signature
$sig = New-PodeJwtSignature -Algorithm $Header.alg -Token $jwt -SecretBytes $secretBytes
$sig = New-PodeJwtSignature -Algorithm $Header.alg -Token $jwt -SecretBytes $Secret

# add the signature and return
$jwt += ".$($sig)"
Expand All @@ -1550,7 +1548,7 @@ Convert and return the payload of a JWT token, verifying the signature by defaul
The JWT token.
.PARAMETER Secret
The Secret, as a byte[], to verify the token's signature.
The Secret, as a string or byte[], to verify the token's signature.
.PARAMETER IgnoreSignature
Skip signature verification, and return the decoded payload.
Expand All @@ -1567,8 +1565,7 @@ function ConvertFrom-PodeJwt
$Token,

[Parameter(ParameterSetName='Signed')]
[byte[]]
$Secret,
$Secret = $null,

[Parameter(ParameterSetName='Ignore')]
[switch]
Expand Down Expand Up @@ -1619,6 +1616,10 @@ function ConvertFrom-PodeJwt
}

# otherwise, we have an alg for the signature, so we need to validate it
if (($null -ne $Secret) -and ($Secret -isnot [byte[]])) {
$Secret = [System.Text.Encoding]::UTF8.GetBytes([string]$Secret)
}

$sig = "$($parts[0]).$($parts[1])"
$sig = New-PodeJwtSignature -Algorithm $header.alg -Token $sig -SecretBytes $Secret

Expand Down
12 changes: 6 additions & 6 deletions src/Public/Core.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,7 @@ function Add-PodeEndpoint
$type = Get-PodeEndpointType -Protocol $Protocol

# are we running as IIS for HTTP/HTTPS? (if yes, force the port, address and protocol)
$isIIS = ($PodeContext.Server.IsIIS -and (@('Http', 'Ws') -icontains $type))
$isIIS = ((Test-PodeIsIIS) -and (@('Http', 'Ws') -icontains $type))
if ($isIIS) {
$Port = [int]$env:ASPNETCORE_PORT
$Address = '127.0.0.1'
Expand All @@ -842,7 +842,7 @@ function Add-PodeEndpoint
}

# are we running as Heroku for HTTP/HTTPS? (if yes, force the port, address and protocol)
$isHeroku = ($PodeContext.Server.IsHeroku -and (@('Http') -icontains $type))
$isHeroku = ((Test-PodeIsHeroku) -and (@('Http') -icontains $type))
if ($isHeroku) {
$Port = [int]$env:PORT
$Address = '0.0.0.0'
Expand Down Expand Up @@ -875,8 +875,8 @@ function Add-PodeEndpoint
throw "An endpoint with the name '$($Name)' has already been defined"
}

# protocol must be https for client certs
if (($Protocol -ine 'https') -and $AllowClientCertificate) {
# protocol must be https for client certs, or hosted behind a proxy like iis
if (($Protocol -ine 'https') -and !(Test-PodeIsHosted) -and $AllowClientCertificate) {
throw "Client certificates are only supported on HTTPS endpoints"
}

Expand Down Expand Up @@ -940,7 +940,7 @@ function Add-PodeEndpoint
} | Measure-Object).Count

# if we're dealing with a certificate, attempt to import it
if (!$isIIS -and !$isHeroku -and ($PSCmdlet.ParameterSetName -ilike 'cert*')) {
if (!(Test-PodeIsHosted) -and ($PSCmdlet.ParameterSetName -ilike 'cert*')) {
# fail if protocol is not https
if (@('https', 'wss') -inotcontains $Protocol) {
throw "Certificate supplied for non-HTTPS/WSS endpoint"
Expand Down Expand Up @@ -993,7 +993,7 @@ function Add-PodeEndpoint
}

# if RedirectTo is set, attempt to build a redirecting route
if (!$isIIS -and !$isHeroku -and ![string]::IsNullOrWhiteSpace($RedirectTo)) {
if (!(Test-PodeIsHosted) -and ![string]::IsNullOrWhiteSpace($RedirectTo)) {
$redir_endpoint = $PodeContext.Server.Endpoints[$RedirectTo]

# ensure the name exists
Expand Down
4 changes: 2 additions & 2 deletions src/Public/Responses.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1297,7 +1297,7 @@ function Set-PodeViewEngine

# override extension with type
if ([string]::IsNullOrWhiteSpace($Extension)) {
$Extension = $Type.ToLowerInvariant()
$Extension = $Type
}

# check if the scriptblock has any using vars
Expand All @@ -1309,7 +1309,7 @@ function Set-PodeViewEngine

# setup view engine config
$PodeContext.Server.ViewEngine.Type = $Type.ToLowerInvariant()
$PodeContext.Server.ViewEngine.Extension = $Extension
$PodeContext.Server.ViewEngine.Extension = $Extension.ToLowerInvariant()
$PodeContext.Server.ViewEngine.ScriptBlock = $ScriptBlock
$PodeContext.Server.ViewEngine.UsingVariables = $usingVars
$PodeContext.Server.ViewEngine.IsDynamic = (@('html', 'md') -inotcontains $Type)
Expand Down
18 changes: 18 additions & 0 deletions src/Public/Utilities.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,24 @@ function Test-PodeIsHeroku
return $PodeContext.Server.IsHeroku
}

<#
.SYNOPSIS
Returns whether or not the server is being hosted behind another application.
.DESCRIPTION
Returns whether or not the server is being hosted behind another application, such as Heroku or IIS.
.EXAMPLE
if (Test-PodeIsHosted) { }
#>
function Test-PodeIsHosted
{
[CmdletBinding()]
param()

return ((Test-PodeIsIIS) -or (Test-PodeIsHeroku))
}

<#
.SYNOPSIS
Creates a new custom lockable object for use with Lock-PodeObject.
Expand Down

0 comments on commit cc45830

Please sign in to comment.