DEV Community

Jesse Houwing for Xebia Microsoft Services

Posted on β€’ Originally published at jessehouwing.net on

1

Update Ghost blogs and pages with PowerShell

Update Ghost blogs and pages with PowerShell

The samples provided by Ghost are in JavaScript, Curl and Python, all languages I'm not fluent in, so I set out to do the same from PowerShell or C#.

The hardest part turned out to be the code to create the correct JWT token to authenticate against Ghost. In their admin panel they provide a set of tokens, but it turns out you can't just use these tokens as-is.

Update Ghost blogs and pages with PowerShell
API Key provided by Ghost

The API key essentially makes up 2 parts:

  1. The Key Identifier, that's the part up to the :
  2. The Secret, that's the part after the :

In order to use this key, we first have to split it into its two parts:

$parts = $adminApiKey -split ":"
$id = $parts[0]
$secret = $parts[1]
Enter fullscreen mode Exit fullscreen mode

We then need to construct a JWT token from this key. I relied on the Posh-JWT package for that part:

Install-Module -Name JWT -force

$key = [Convert]::FromHexString($secret) # only works in PowerShell Core

$jwttoken = New-Jwt `
  -Header (
    @{
      "alg" = "HS256"
      "kid" = $id
      "typ" = "JWT"
    } | ConvertTo-Json
  ) `
  -PayloadJson (
    @{
      "exp" = ([DateTimeOffset](Get-Date).AddMinutes(2)).ToUnixTimeSeconds()
      "iat" = ([DateTimeOffset](Get-Date)).ToUnixTimeSeconds()
      "aud" = "/admin/"
    } | ConvertTo-Json) 
  -Secret $key
Enter fullscreen mode Exit fullscreen mode

With this token, you can then invoke the Ghost API.

$headers = @{
  Authorization = "Ghost $jwttoken"
  "Content-Type" = "application/json"
}

$baseUri = "https://scrumbug.ghost.io/ghost/api"

$result = Invoke-RestMethod `
  -Uri "$baseUri/admin/pages/" `
  -Method GET `
  -Headers $headers     
Enter fullscreen mode Exit fullscreen mode

As I said, I used this code to automatically sync my Scrum.org classes to this blog. You can find the (private) Ghost update GitHub Action here. To keep my secrets secure I added a couple of extra lines of code to register my secrets with the runner:

Write-Output "::add-mask::$id"
...
Write-Output "::add-mask::$secret"
...
Write-Output "::add-mask::$key"
...
Write-Output "::add-mask::$jwttoken"
Enter fullscreen mode Exit fullscreen mode

Make sure to always register your secrets every time they change their shape or representation to prevent your secrets from leaking into the GitHub Action logs.

End result? My classes are automatically updated πŸŽ‰:

Update Ghost blogs and pages with PowerShell
Github actions workflow runs successfully

Quadratic AI

Quadratic AI – The Spreadsheet with AI, Code, and Connections

  • AI-Powered Insights: Ask questions in plain English and get instant visualizations
  • Multi-Language Support: Seamlessly switch between Python, SQL, and JavaScript in one workspace
  • Zero Setup Required: Connect to databases or drag-and-drop files straight from your browser
  • Live Collaboration: Work together in real-time, no matter where your team is located
  • Beyond Formulas: Tackle complex analysis that traditional spreadsheets can't handle

Get started for free.

Watch The Demo πŸ“Šβœ¨

Top comments (0)

πŸ‘‹ Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay