Skip to content

Commit

Permalink
chore: first draft
Browse files Browse the repository at this point in the history
  • Loading branch information
devthejo committed Dec 16, 2024
0 parents commit c5edd93
Show file tree
Hide file tree
Showing 31 changed files with 6,479 additions and 0 deletions.
37 changes: 37 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Version Control
.git
.gitignore

# IDE and editor files
.idea/
.vscode/
*.swp
*.swo
*~

# Node
**/node_modules
.env*
*.log
tmp/
temp/

# Docker related
docker-compose*.yml
Dockerfile*
.docker/

# Documentation
*.md
docs/

# Misc
.DS_Store
*.pprof
*.cpu
*.mem
*.trace

# Project specific
/action
/examples
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
root = true

[*]
end_of_line = lf
insert_final_newline = true

[*.{js,json,yml}]
charset = utf-8
indent_style = space
indent_size = 2
23 changes: 23 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Server Configuration
PORT=3000

# GitHub App Configuration
GITHUB_APP_ID=123456

# Private key can be in any of these formats:

# 1. Single line with \n:
GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA1c7+9z5Pad7OejecsQ0bu...\n-----END RSA PRIVATE KEY-----"

# 2. Multiline with actual line breaks:
# GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
# MIIEpAIBAAKCAQEA1c7+9z5Pad7OejecsQ0bu...
# [ Rest of the private key content ]
# -----END RSA PRIVATE KEY-----"

# 3. Single line without \n (will be formatted automatically):
# GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----MIIEpAIBAAKCAQEA1c7+9z5Pad7OejecsQ0bu...-----END RSA PRIVATE KEY-----"

# OIDC Configuration
# This should match the audience value used in GitHub Actions
OIDC_AUDIENCE=your-audience-value
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/.yarn/** linguist-vendored
/.yarn/releases/* binary
/.yarn/plugins/**/* binary
57 changes: 57 additions & 0 deletions .github/workflows/debug.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Debug OIDC Token

on:
workflow_dispatch:

permissions:
id-token: write

jobs:
debug:
runs-on: ubuntu-latest
steps:
- name: Repository Info
run: |
echo "=== Repository Information ==="
echo "Repository: ${{ github.repository }}"
echo "Owner: ${{ github.repository_owner }}"
echo "Ref: ${{ github.ref }}"
echo "Event: ${{ github.event_name }}"
- name: Get OIDC Token
run: |
# Get the token
TOKEN="$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=test-audience")"
echo "=== Raw Token Response ==="
echo "$TOKEN"
echo
echo "=== Token Structure ==="
# Extract and decode each part of the JWT if it's not in JSON format
if echo "$TOKEN" | jq -e . >/dev/null 2>&1; then
echo "Token is in JSON format"
VALUE=$(echo "$TOKEN" | jq -r .value)
echo "Header:"
echo "$VALUE" | cut -d. -f1 | base64 -d 2>/dev/null | jq .
echo
echo "Payload:"
echo "$VALUE" | cut -d. -f2 | base64 -d 2>/dev/null | jq .
else
echo "Token is in raw JWT format"
echo "Header:"
echo "$TOKEN" | cut -d. -f1 | base64 -d 2>/dev/null | jq .
echo
echo "Payload:"
echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq .
fi
echo
echo "=== Test Commands ==="
echo "# Export token and test"
echo "export OIDC_TOKEN='$TOKEN'"
echo "DEBUG=true ./scripts/test-request.sh http://localhost:3000"
echo
echo "# Or use directly"
echo "DEBUG=true ./scripts/test-request.sh http://localhost:3000 '$TOKEN'"
48 changes: 48 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Docker

on:
push:
branches: [main]

permissions:
packages: write

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Get version from package.json
id: package-version
run: |
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest
type=raw,value=${{ steps.package-version.outputs.version }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
42 changes: 42 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Release

on:
push:
branches: [main]
workflow_dispatch:

permissions:
contents: write
pull-requests: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- uses: actions/setup-node@v4
with:
node-version: "22"
cache: yarn

- name: Install dependencies
run: yarn

- name: Git Identity
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
- name: Create Release
run: |
yarn release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Push changes
run: |
git push --follow-tags origin main
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/.env

# node
node_modules

# yarn berry
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
# !.yarn/cache
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22
9 changes: 9 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"semi": false,
"tabWidth": 2,
"printWidth": 100,
"singleQuote": false,
"trailingComma": "es5",
"bracketSpacing": true,
"jsxBracketSameLine": false
}
158 changes: 158 additions & 0 deletions .yarn/plugins/@yarnpkg/plugin-fetch.cjs

Large diffs are not rendered by default.

934 changes: 934 additions & 0 deletions .yarn/releases/yarn-4.5.3.cjs

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
nodeLinker: node-modules

plugins:
- checksum: 261acd6dc39c0b6178a049fea5f33b6ce6eed61ad87d1227efcd97689d182074a222a5401d6c302cc19387097ffdd8a5787dca6680093f1f30a6209f62d6cb2f
path: .yarn/plugins/@yarnpkg/plugin-fetch.cjs
spec: "https://codeberg.org/devthefuture/yarn-plugin-fetch/raw/branch/master/bundles/@yarnpkg/plugin-fetch.js"

yarnPath: .yarn/releases/yarn-4.5.3.cjs
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM node:22-alpine AS build

USER 1000
WORKDIR /app
ENV NODE_ENV=production

COPY --chown=1000:1000 yarn.lock .yarnrc.yml ./
COPY --chown=1000:1000 .yarn .yarn
RUN yarn fetch workspaces focus --production && yarn cache clean

COPY server ./server
COPY package.json ./

EXPOSE 3000
CMD ["yarn", "start"]
121 changes: 121 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# 🦉 TokenBureau

TokenBureau is a secure service for generating GitHub App tokens using OIDC verification. It includes both a server implementation and a GitHub Action for easy integration.

## GitHub Action Usage

Add the TokenBureau action to your workflow:

```yaml
permissions:
id-token: write # Required for OIDC token generation

steps:
- name: Get GitHub App Token
id: token
uses: SocialGouv/token-bureau@v1
with:
token-bureau-url: https://your-token-bureau-service.com
audience: your-audience-value

# Use the token in subsequent steps
- name: Use Token
env:
GITHUB_TOKEN: ${{ steps.token.outputs.token }}
run: |
# Your commands using the token
```
### Action Outputs
- `token`: The generated GitHub App token
- `expires_at`: Token expiration timestamp
- `installation_id`: GitHub App installation ID

## Server Setup

### Using Docker

```bash
# Build the image
docker build -t token-bureau .
# Run the container
docker run -p 3000:3000 \
-e GITHUB_APP_ID=your_app_id \
-e GITHUB_PRIVATE_KEY="$(cat path/to/private-key.pem)" \
-e OIDC_AUDIENCE=your_audience \
token-bureau
```

### Manual Setup

1. Clone the repository:
```bash
git clone https://github.com/SocialGouv/token-bureau.git
cd token-bureau
```

2. Copy the environment template:
```bash
cp .env.example .env
```

3. Configure environment variables in `.env`:
```env
# Server Configuration
PORT=3000
# GitHub App Configuration
GITHUB_APP_ID=your_github_app_id
GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
your_private_key_here
-----END RSA PRIVATE KEY-----"
# OIDC Configuration
OIDC_AUDIENCE=your_external_service_audience
```

4. Install dependencies and start the server:
```bash
yarn install
yarn start
```

## GitHub App Setup

1. Create a GitHub App:
- Navigate to **Settings** > **Developer settings** > **GitHub Apps** > **New GitHub App**
- Set required permissions:
- **Contents**: **Read & Write**
- **Metadata**: **Read**

2. Install the GitHub App:
- Go to the **Install App** tab
- Select your organization/account
- Choose repositories that need token generation

3. Configure the app:
- Generate and download the private key
- Note the App ID
- Add these to your environment configuration

## Security Features

- OIDC token verification using GitHub's JWKS endpoint
- Automatic token scoping to the requesting repository
- Environment variable validation
- Request retry logic with proper error handling
- Runs as non-root user in Docker

## Development

To run the server in development mode with auto-reload:

```bash
yarn dev
```

## License

MIT
Loading

0 comments on commit c5edd93

Please sign in to comment.