Skip to content

Initial Import #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 2, 2022
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
20 changes: 20 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.224.3/containers/go/.devcontainer/base.Dockerfile

# [Choice] Go version (use -bullseye variants on local arm64/Apple Silicon): 1, 1.16, 1.17, 1-bullseye, 1.16-bullseye, 1.17-bullseye, 1-buster, 1.16-buster, 1.17-buster
ARG VARIANT="1.18-bullseye"
FROM mcr.microsoft.com/vscode/devcontainers/go:0-${VARIANT}

# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
ARG NODE_VERSION="none"
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi

# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>

# [Optional] Uncomment the next lines to use go get to install anything else you need
# USER vscode
# RUN go get -x <your-dependency-or-tool>

# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
42 changes: 42 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.224.3/containers/go
{
"name": "Go",
"build": {
"dockerfile": "Dockerfile",
"args": {
// Update the VARIANT arg to pick a version of Go: 1, 1.18, 1.17
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local arm64/Apple Silicon.
"VARIANT": "1-bullseye",
// Options
"NODE_VERSION": "lts/*"
}
},
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],

// Set *default* container specific settings.json values on container create.
"settings": {
"go.toolsManagement.checkForUpdates": "local",
"go.useLanguageServer": true,
"go.gopath": "/go"
},

// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"golang.Go"
],

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "go version",

// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode",
"features": {
"git": "os-provided",
"github-cli": "latest"
}
}
22 changes: 22 additions & 0 deletions .github/workflows/action-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
name: Test Debugger Action
on:
pull_request:
branches:
- main
workflow_dispatch:

jobs:
oidc_debug_test:
permissions:
contents: read
id-token: write
runs-on: ubuntu-latest
name: A test of the oidc debugger
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Debug OIDC Claims
uses: ./
with:
audience: 'https://github.com/github'
19 changes: 19 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
name: Test OIDC Debugger
on:
pull_request:
branches:
- main
workflow_dispatch:

jobs:
test:
permissions:
contents: read
id-token: write
runs-on: ubuntu-latest
steps:
- name: git checkout
uses: actions/checkout@v3
- name: run oidc-debug.go
run: go run cmd/oidc-debug.go -audience "https://github.com/github"
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM alpine:latest
RUN apk add --no-cache go

COPY . .

ENTRYPOINT ["/entrypoint.sh"]
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,25 @@
# actions-oidc-debugger
An Action for printing OIDC claims in GitHub Actions.

This action requests a JWT and prints the claims included within the JWT received from GitHub Actions.

## Usage

```yaml

on: [pull_request]

jobs:
oidc_debug_test:
permissions:
contents: read
id-token: write
runs-on: ubuntu-latest
name: A test of the oidc debugger
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Debug OIDC Claims
uses: github/actions-oidc-debugger@v1
with:
audience: 'https://github.com/github
```
11 changes: 11 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: 'OIDC Debugger'
description: 'Print the GitHub Actions OIDC claims.'
inputs:
audience:
description: 'The audience to use when requesting the JWT.'
required: true
runs:
using: 'docker'
image: 'Dockerfile'
args:
- ${{ inputs.audience }}
135 changes: 135 additions & 0 deletions actionsoidc/actions-oidc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package actionsoidc

import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"

"github.com/golang-jwt/jwt"
)

type ActionsOIDCClient struct {
// the url to fetch the jwt
TokenRequestURL string
// the audience for the jwt
Audience string
// the token used to retrieve the jwt, not the jwt
RequestToken string
}

type ActionsJWT struct {
Count int
Value string
ParsedToken *jwt.Token
}

func GetEnvironmentVariable(e string) (string, error) {
value := os.Getenv(e)
if value == "" {
return "", fmt.Errorf("missing %s from envrionment", e)
}
return value, nil
}

func QuitOnErr(e error) {
if e != nil {
log.Fatal(e)
}
}

// construct a new ActionsOIDCClient
func NewActionsOIDCClient(tokenURL string, audience string, token string) (ActionsOIDCClient, error) {
c := ActionsOIDCClient{
TokenRequestURL: tokenURL,
Audience: audience,
RequestToken: token,
}
err := c.BuildTokenURL()
return c, err
}

func DefaultOIDCClient(audience string) ActionsOIDCClient {
tokenURL, err := GetEnvironmentVariable("ACTIONS_ID_TOKEN_REQUEST_URL")
QuitOnErr(err)
token, err := GetEnvironmentVariable("ACTIONS_ID_TOKEN_REQUEST_TOKEN")
QuitOnErr(err)

c, err := NewActionsOIDCClient(tokenURL, audience, token)
QuitOnErr(err)

return c
}

// this function uses an ActionsOIDCClient to build the complete URL
// to request a jwt
func (c *ActionsOIDCClient) BuildTokenURL() error {
parsed_url, err := url.Parse(c.TokenRequestURL)
if err != nil {
return fmt.Errorf("failed to parse URL: %w", err)
}

if c.Audience != "" {
query := parsed_url.Query()
query.Set("audience", c.Audience)
parsed_url.RawQuery = query.Encode()
}
return nil
}

// retrieve an actions oidc token
func (c *ActionsOIDCClient) GetJWT() (*ActionsJWT, error) {
request, err := http.NewRequest("GET", c.TokenRequestURL, nil)
if err != nil {
return nil, err
}

request.Header.Set("Authorization", "Bearer "+c.RequestToken)

var httpClient http.Client
response, err := httpClient.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()

if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("received non-200 from jwt api: %s", http.StatusText((response.StatusCode)))
}

rawBody, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, err
}

var jwt ActionsJWT
err = json.Unmarshal(rawBody, &jwt)

return &jwt, err
}

func (j *ActionsJWT) Parse() {
j.ParsedToken, _ = jwt.Parse(j.Value, func(token *jwt.Token) (interface{}, error) {
// Don't forget to validate the alg is what you expect:
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}

// we don't need a real check here
return []byte{}, nil
})
}

func (j *ActionsJWT) PrettyPrintClaims() string {
if claims, ok := j.ParsedToken.Claims.(jwt.MapClaims); ok {
jsonClaims, err := json.MarshalIndent(claims, "", " ")
if err != nil {
fmt.Println(fmt.Errorf("%w", err))
}
return string(jsonClaims)
}
return ""
}
25 changes: 25 additions & 0 deletions cmd/oidc-debug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
"flag"
"fmt"

"github.com/github/actions-oidc-debugger/actionsoidc"
)

func main() {

audience := flag.String("audience", "https://github.com/", "the audience for the requested jwt")
flag.Parse()

if *audience == "https://github.com/" {
actionsoidc.QuitOnErr(fmt.Errorf("-audience cli argument must be specified"))
}

c := actionsoidc.DefaultOIDCClient(*audience)
jwt, err := c.GetJWT()
actionsoidc.QuitOnErr(err)

jwt.Parse()
fmt.Print(jwt.PrettyPrintClaims())
}
3 changes: 3 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh -l

go run cmd/oidc-debug.go -audience $1
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/github/actions-oidc-debugger

go 1.18

require github.com/golang-jwt/jwt v3.2.2+incompatible
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
4 changes: 4 additions & 0 deletions vendor/github.com/golang-jwt/jwt/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions vendor/github.com/golang-jwt/jwt/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions vendor/github.com/golang-jwt/jwt/MIGRATION_GUIDE.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading