Skip to content

Commit

Permalink
Merge pull request #754 from Badgerati/develop
Browse files Browse the repository at this point in the history
v2.3.0
  • Loading branch information
Badgerati authored Jun 1, 2021
2 parents a11f7c8 + 1dd333a commit 53b9a81
Show file tree
Hide file tree
Showing 49 changed files with 1,814 additions and 138 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
[![PowerShell](https://img.shields.io/powershellgallery/dt/pode.svg?label=PowerShell&colorB=085298)](https://www.powershellgallery.com/packages/Pode)
[![Docker](https://img.shields.io/docker/pulls/badgerati/pode.svg?label=Docker)](https://hub.docker.com/r/badgerati/pode/)

> 💝 A lot of my free time, evenings, and weekends goes into making Pode happen; please do consider sponsoring as it will really help! 😊
Pode is a Cross-Platform framework for creating web servers to host [REST APIs](https://badgerati.github.io/Pode/Tutorials/Routes/Overview/), [Web Pages](https://badgerati.github.io/Pode/Tutorials/Routes/Examples/WebPages/), and [SMTP/TCP](https://badgerati.github.io/Pode/Hosting/SmtpServer/) Servers. Pode also allows you to render dynamic files using [`.pode`](https://badgerati.github.io/Pode/Tutorials/Views/Pode/) files, which are just embedded PowerShell, or other [Third-Party](https://badgerati.github.io/Pode/Tutorials/Views/ThirdParty/) template engines. Plus many more features, including [Azure Functions](https://badgerati.github.io/Pode/Hosting/AzureFunctions/) and [AWS Lambda](https://badgerati.github.io/Pode/Hosting/AwsLambda/) support!

<p align="center">
Expand All @@ -19,7 +21,7 @@ Pode is a Cross-Platform framework for creating web servers to host [REST APIs](

See [here](https://badgerati.github.io/Pode/Getting-Started/FirstApp) for building your first app! Don't know HTML, CSS, or JavaScript? No problem! [Pode.Web](https://github.com/Badgerati/Pode.Web) is currently a work in progress, and lets you build web pages using purely PowerShell!

## Documentation
## 📘 Documentation

All documentation and tutorials for Pode can be [found here](https://badgerati.github.io/Pode) - this documentation will be for the latest release.

Expand All @@ -31,7 +33,7 @@ Invoke-Build Docs

Then navigate to `http://127.0.0.1:8000` in your browser.

## Features
## 🚀 Features

* Cross-platform using PowerShell Core (with support for PS5)
* Docker support, including images for ARM/Raspberry Pi
Expand All @@ -58,7 +60,7 @@ Then navigate to `http://127.0.0.1:8000` in your browser.
* Generate/bind self-signed certificates
* (Windows) Open the hosted server as a desktop application

## Install
## 📦 Install

You can install Pode from either Chocolatey, the PowerShell Gallery, or Docker:

Expand All @@ -73,7 +75,7 @@ Install-Module -Name Pode
docker pull badgerati/pode
```

## Contributing
## 🙌 Contributing

> The full contributing guide can be [found here](https://github.com/Badgerati/Pode/blob/develop/.github/CONTRIBUTING.md)
Expand Down
134 changes: 122 additions & 12 deletions docs/Hosting/IIS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Pode has support for you to host your server via IIS!

When you host your server through IIS, Pode can detect this and internally set the server type and endpoints to automatically work with IIS. This allows IIS to deal with binding, HTTPS and Certificates, as well as external traffic, etc.
When you host your server through IIS, Pode will detect this and internally set the server type and endpoints to automatically work with IIS. This allows IIS to deal with binding, HTTPS and Certificates, as well as external traffic, etc.

!!! important
This being IIS, it is for Windows only!
Expand Down Expand Up @@ -34,9 +34,9 @@ pwsh -c "Install-Module Pode -Scope AllUsers"
```

!!! note
Sometimes you may need to run `iisreset`, otherwise IIS will return 502 errors.
Sometimes you may need to run `iisreset` after installing all of the above, otherwise IIS will return 502 errors.

## Server
## Configuration

The first thing you'll need to do so IIS can host your server is, in the same directory as your Pode server's `.ps1` root script, create a `web.config` file. This file should look as follows, but make sure you replace the `.\server.ps1` with the path to your actual server script:

Expand Down Expand Up @@ -70,14 +70,26 @@ The first thing you'll need to do so IIS can host your server is, in the same di
</configuration>
```

Once done, you can setup IIS in the normal way:
## IIS Setup

* Create an Application Pool
* Create a website, and set the physical path to the root directory of your Pode server
* Setup a binding (something like HTTP on *:8080 - IP Address can be anything)
* Then, navigate to the IIS binding endpoint
With the `web.config` file in place, it's then time to setup the site in IIS. The first thing to do is open up the IIS Manager, then once open, follow the below steps to setup your site:

Pode automatically detects that it is running via IIS, and it changes certain attributes of your Pode server so they work with IIS:
1. In the left pane, expand the Server and then the Sites folders
2. Right click the "Application Pools" folder
1. Enter a name for your Application Pool, just the name of your site will do, such as "pode.example.com"
2. Select OK to create the Application Pool
3. Right click the Sites folder, and select "Add Website..."
1. Enter the name of your website, such as "pode.example.com"
2. Select the Application Pool that we created above
3. Set the Physical Path to the root directory of your Pode server's script (just the directory, not the ps1 itself)
4. Select either HTTP or HTTPS for your binding
5. Leave IP Address as "All Unassigned", and either leave the Port as 80/443 or change to what you need
6. Optionally enter the host name of your site, such as "pode.example.com" (usually required for HTTPS)
7. If HTTPS, select "Require SNI"
8. If HTTPS, select the required certificate from the dropdown
9. Select OK to create the Site

At this point, your site is now created in IIS, and you should be able to navigate to the hostname/IP and port combination you setup above for the IIS site. Pode automatically detects that it is running via IIS, and it changes certain attributes of your Pode server so they work with IIS:

* Endpoints have their Address set to `127.0.0.1` (IIS needs Pode to be on localhost)
* Endpoints have their Port set to `ASPNETCORE_PORT`
Expand All @@ -86,17 +98,115 @@ Pode automatically detects that it is running via IIS, and it changes certain at
This allows you to write a Pode server that works locally, but will also automatically work under IIS without having to change anything!

!!! note
This does mean that Pode will force all endpoints to `127.0.0.1:PORT`. So if you had two different IPs before, they'll be merged into one.
This does mean that Pode will force all endpoints to `127.0.0.1:PORT`. So if you had two different IPs before, they'll be merged into one. Something to be aware of if you assign routes to specific endpoints, as under IIS this won't work.

### Advanced/Domain

The above IIS site setup works, but only for simple sites. If you require the use of the Active Directory module, or your site to be running as a different user then follow the steps below.

#### Active Directory

By default a newly created site will be running as ApplicationPoolIdentity. In order to use the Active Directory module, your IIS site will need to be running as a domain user:

1. Open IIS, and select the Application Pools folder
2. Right click your Application Pool, and select "Advanced Settings..."
3. Under "Process Module", click the "..." of the "Identity" setting
4. Select "Custom account", and change the account to the credentials of a valid domain user
5. Select OK

If you've enabled Basic authentication in IIS for you site, you'll also need to edit the domain there as well:

1. Open IIS, and expand the Sites folder
2. Select your Site
3. In the middle pane, under IIS, select "Authentication"
4. Right click "Basic Authentication" (if it's enabled)
5. Edit the domain to your domain
6. Select OK

Sometimes you might run into issues using the Active Directory module under IIS - such as the following error:

```plain
Creating a new session for implicit remoting of "Get-ADUser" command...
```

If this happens, you'll need to make your AD calls using `Invoke-Command`:

```powershell
Invoke-Command -ArgumentList $username -ScriptBlock {
param($username)
Import-Module -Name ActiveDirectory
Get-ADUser -Identity $username
}
```

#### Change User

To change the user your site is running as:

1. Open IIS, and select the Application Pools folder
2. Right click your Application Pool, and select "Advanced Settings..."
3. Under "Process Module", click the "..." of the "Identity" setting
4. Change the user to either an inbuilt one, or a custom local/domain user
5. Select OK

## HTTPS

Although Pode does have support for HTTPS, when running via IIS it takes control of HTTPS for us - this is why the endpoints are forced to HTTP.

You can setup a binding in IIS for HTTPS with a Certificate, and IIS will deal with SSL for you.
You can setup a binding in IIS for HTTPS with a Certificate, and IIS will deal with SSL for you:

1. Open IIS, and expand the Sites folder
2. Right click your Site, and select "Edit Bindings..."
3. Select "Add..."
4. Select HTTPS for your binding
5. Leave IP Address as "All Unassigned", and either leave the Port as 443 or change to what you need
6. Enter the host name of your site, such as "pode.example.com"
7. Select "Require SNI"
8. Select the required certificate from the dropdown
9. Select OK to create the Binding

## Recycling

By default, IIS has certain settings that will recycle/shutdown your Application Pools. This will cause some requests to "spin-up" the site for the first time, and go slow.

To help prevent this, below are some of the common setting that can be altered to stop IIS recycling/shutting down your site:

1. Open IIS, and select the Application Pools folder
2. Right click your Application Pool, and select "Advanced Settings..."
3. Under "Process Model", to stop IIS shutting down your site
1. Set the "Idle Time-out" to 0
4. Under "Recycling", to stop IIS recycling your site
1. Set the "Regular Time Interval" to 0
2. Remove all times from "Specific Times"

This isn't bulletproof, and IIS can sometimes restart your site if it feels like it. Also make sure that there are no periodic processes anywhere that might recycle Application Pools, or run `iisreset`.

When IIS does restart your site, the log file should show the usual Pode "Terminating" message, but preceded with "(IIS Shutdown)".

### Debug Line

Whenever IIS recycles/shuts down your site, you may see a debug line in your logs if the initial HTTP shutdown request fails, such as:

```plain
Entering debug mode. Use h or ? for help.
At C:\Program Files\PowerShell\Modules\Pode\2.0.3\Public\Core.ps1:176 char:13
+ $key = Get-PodeConsoleKey
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
[DBG]: PS D:\wwwroot\sitename>>
```

This is nothing to worry about, and is purely just IIS terminating the PowerShell runspace to shutdown the Application Pool.

## ASP.NET Token

When hosted via IIS, Pode inspects every request to make sure the mandatory `MS-ASPNETCORE-TOKEN` header is present. This is a token supplied by IIS, and if it's missing Pode will reject the request with a 400 response.

There's nothing you need to do, IIS informs Pode about the token for you, and IIS will add the header to the requests automatically for you as well.

## IIS Authentication

If you decide to use IIS for Windows Authentication, then you can retrieve the authenticated user in Pode. This is done using the [`Add-PodeAuthIIS`](../../Functions/Authentication/Add-PodeAuthIIS) function, and it will check for the `MS-ASPNETCORE-WINAUTHTOKEN` header from IIS. The function creates a custom Authentication Type and Method, and can be used on Routes like other Authentications in Pode:
If you decide to use IIS for Windows Authentication, then you can retrieve the authenticated user in Pode. This is done using the [`Add-PodeAuthIIS`](../../Functions/Authentication/Add-PodeAuthIIS) function, and it will check for the `MS-ASPNETCORE-WINAUTHTOKEN` header from IIS. The function creates a custom Authentication Type and Method, and can be used on Routes like other authentications in Pode:

```powershell
Start-PodeServer {
Expand Down
110 changes: 110 additions & 0 deletions docs/Tutorials/Authentication/Methods/ApiKey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# API Key

API key authentication lets you authenticate a user based on an API key in either the header, a cookie, or in the query string.

Depending on the location, Pode looks for an API key in the default location names:

* Header: `X-API-KEY`
* Cookie: `X-API-KEY`
* Query: `api_key`

Pode looks for the Header by default, and these can be changed as shown below.

## Setup

To setup and start using API key authentication in Pode you can use `New-PodeAuthScheme -ApiKey`, and then pipe the returned object into [`Add-PodeAuth`](../../../../Functions/Authentication/Add-PodeAuth). The parameter supplied to the [`Add-PodeAuth`](../../../../Functions/Authentication/Add-PodeAuth) function's ScriptBlock is the `$key` that Pode found in either the header, cookie or query string:

```powershell
Start-PodeServer {
New-PodeAuthScheme -ApiKey | Add-PodeAuth -Name 'Authenticate' -Sessionless -ScriptBlock {
param($key)
# check if the key is valid, and get user
return @{ User = $user }
}
}
```

By default, Pode will look for an `X-API-KEY` header in the request. You can change this to Cookie or Query by using the `-Location` parameter. To change the name of what Pode looks for, you can use `-LocationName`.

For example, to look for an `appId` query value:

```powershell
Start-PodeServer {
New-PodeAuthScheme -ApiKey -Location Query -LocationName 'appId' | Add-PodeAuth -Name 'Authenticate' -Sessionless -ScriptBlock {
param($key)
# check if the key is valid, and get user
return @{ User = $user }
}
}
```

If the API key can't be found, then a 401 response will be returned.

## Middleware

Once configured you can start using API key authentication to validate incoming requests. You can either configure the validation to happen on every Route as global Middleware, or as custom Route Middleware.

The following will use API key authentication to validate every request on every Route:

```powershell
Start-PodeServer {
Add-PodeAuthMiddleware -Name 'GlobalAuthValidation' -Authentication 'Authenticate'
}
```

Whereas the following example will use API key authentication to only validate requests on specific a Route:

```powershell
Start-PodeServer {
Add-PodeRoute -Method Get -Path '/info' -Authentication 'Authenticate' -ScriptBlock {
# logic
}
}
```

## JWT

You can supply a JWT using API key authentication, for more details [see here](../JWT).

## Full Example

The following full example of API key authentication will setup and configure authentication, validate the key from the `X-API-KEY` header, and then validate on a specific Route:

```powershell
Start-PodeServer {
Add-PodeEndpoint -Address * -Port 8080 -Protocol Http
# setup apikey authentication to validate a user
New-PodeAuthScheme -ApiKey | Add-PodeAuth -Name 'Authenticate' -Sessionless -ScriptBlock {
param($key)
# here you'd check a real storage, this is just for example
if ($key -eq 'test-key') {
return @{
User = @{
'ID' ='M0R7Y302'
'Name' = 'Morty'
'Type' = 'Human'
}
}
}
# authentication failed
return $null
}
# check the request on this route against the authentication
Add-PodeRoute -Method Get -Path '/cpu' -Authentication 'Authenticate' -ScriptBlock {
Write-PodeJsonResponse -Value @{ 'cpu' = 82 }
}
# this route will not be validated against the authentication
Add-PodeRoute -Method Get -Path '/memory' -ScriptBlock {
Write-PodeJsonResponse -Value @{ 'memory' = 14 }
}
}
```
8 changes: 4 additions & 4 deletions docs/Tutorials/Authentication/Methods/AzureAD.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ With the Client and Tenant ID, plus the Client Secret, you can now setup Azure A

### Authorisation Code

To setup and start using Azure AD Authentication in Pode you use `New-PodeAuthAzureADScheme`, and then pipe this into the [`Add-PodeAuth`](../../../../Functions/Authentication/Add-PodeAuth) function:
To setup and start using Azure AD authentication in Pode you use `New-PodeAuthAzureADScheme`, and then pipe this into the [`Add-PodeAuth`](../../../../Functions/Authentication/Add-PodeAuth) function:

```powershell
Start-PodeServer {
Expand Down Expand Up @@ -64,8 +64,8 @@ Start-PodeServer {

## Requests using Basic Authentication

To authenticate against Azure Active Directory with Applications that do not support Modern Authentication (for example PowerShell Invoke-RestMethod), you will need to use Basic Authentication.
This method only works if you're either using Password Hash Sync (PHS), Pass-through Authentication (PTA) or both. If you're using claim based authentication against another IdP like Active Directory Federation Services (ADFS) then this will not work as the Azure AD does not know the users' credentials.
To authenticate against Azure Active Directory with Applications that do not support Modern authentication (for example PowerShell Invoke-RestMethod), you will need to use Basic authentication.
This method only works if you're either using Password Hash Sync (PHS), Pass-through authentication (PTA) or both. If you're using claim based authentication against another IdP like Active Directory Federation Services (ADFS) then this will not work as the Azure AD does not know the users' credentials.

The client side may look like this:

Expand All @@ -76,7 +76,7 @@ $res.Form[0].password = 'password'
Invoke-RestMethod -Url 'http://localhost:8080' -WebSession $session -Body $res.Form[0]
```

The Pode side needs to be configured to allow basic authentication as well. This can be done side by side with Form based Authentication using this example
The Pode side needs to be configured to allow basic authentication as well. This can be done side by side with Form based authentication using this example

```powershell
$form = New-PodeAuthScheme -Form
Expand Down
Loading

0 comments on commit 53b9a81

Please sign in to comment.