Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
11 changes: 10 additions & 1 deletion .github/workflows/build-and-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,17 @@ jobs:
target: release
base_image: ${{ github.sha }}

build-custom-issuer:
needs: [build-base]
uses: ./.github/workflows/build-custom-issuer.yaml
secrets: inherit
with:
push: true
target: release
base_image: ${{ github.sha }}

deploy:
needs: [build-relayer, build-attester]
needs: [build-relayer, build-attester, build-custom-issuer]
uses: ./.github/workflows/deploy.yaml
secrets: inherit
with:
Expand Down
58 changes: 58 additions & 0 deletions .github/workflows/build-custom-issuer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: "Build custom-issuer image"

on:
workflow_call:
inputs:
push:
required: true
type: boolean
target:
required: true
type: string
base_image:
required: true
type: string

jobs:
build:
name: Build
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
# Checkout repository under $GITHUB_WORKSPACE path
- name: Repository checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PUSH_TOKEN }}

# Configure tag name
- name: Sets env vars
run: |
echo "DOCKER_IMAGE_NAME=${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}-custom-issuer:${GITHUB_SHA:0:8}" >> $GITHUB_ENV

# Build docker image
- name: Build docker image
uses: docker/build-push-action@v4
with:
context: .
file: docker/custom-issuer.Dockerfile
target: ${{ inputs.target }}
push: ${{ inputs.push }}
tags: ${{ env.DOCKER_IMAGE_NAME }}
build-args: |
BASE_IMAGE=${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}-base:${{ inputs.base_image }}
TURBO_TEAM=peersyst
secrets: |
turbo_token=${{ secrets.TURBO_TOKEN }}
Comment on lines +47 to +58
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

docker/build-push-action latest version releases GitHub Actions

💡 Result:

Latest stable major release: v6. Latest published package version: v6.18.0 (current latest). [1][2]

Sources:

  • docker/build-push-action repo (README showing v6 as stable). [1]
  • Package versions page listing v6.18.0 as the latest. [2]

Update docker/build-push-action to v6.

The docker/build-push-action@v4 is outdated. Update to v6.18.0 (the latest stable version).

♻️ Proposed update
       - name: Build docker image
-        uses: docker/build-push-action@v4
+        uses: docker/build-push-action@v6
         with:
           context: .
           file: docker/custom-issuer.Dockerfile
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
uses: docker/build-push-action@v4
with:
context: .
file: docker/custom-issuer.Dockerfile
target: ${{ inputs.target }}
push: ${{ inputs.push }}
tags: ${{ env.DOCKER_IMAGE_NAME }}
build-args: |
BASE_IMAGE=${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}-base:${{ inputs.base_image }}
TURBO_TEAM=peersyst
secrets: |
turbo_token=${{ secrets.TURBO_TOKEN }}
uses: docker/build-push-action@v6
with:
context: .
file: docker/custom-issuer.Dockerfile
target: ${{ inputs.target }}
push: ${{ inputs.push }}
tags: ${{ env.DOCKER_IMAGE_NAME }}
build-args: |
BASE_IMAGE=${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}-base:${{ inputs.base_image }}
TURBO_TEAM=peersyst
secrets: |
turbo_token=${{ secrets.TURBO_TOKEN }}
🧰 Tools
🪛 actionlint (1.7.10)

47-47: the runner of "docker/build-push-action@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🤖 Prompt for AI Agents
In @.github/workflows/build-custom-issuer.yaml around lines 47 - 58, Replace the
outdated action reference "uses: docker/build-push-action@v4" with the latest
stable release "uses: docker/build-push-action@v6.18.0" in the workflow block
that configures the Docker build (the block referencing file:
docker/custom-issuer.Dockerfile and inputs like target, push, tags, build-args,
secrets); update only the version specifier for docker/build-push-action to
v6.18.0 and verify the existing keys (context, file, target, push, tags,
build-args, secrets) remain valid with v6.

1 change: 1 addition & 0 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ jobs:
--set-string timestamp="${{ env.NOW }}" \
--set-string tagRelayer="${{ env.TAG }}" \
--set-string tagAttester="${{ env.TAG }}" \
--set-string tagCustomIssuer="${{ env.TAG }}" \
--debug

# Send final Slack message if any previous step has failed
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/manual-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ on:
description: "Attester Tag image to deploy"
required: true
type: string
custom-issuer-tag:
description: "Custom Issuer Tag image to deploy"
required: true
type: string
environment:
description: "Environment to deploy"
required: true
Expand Down Expand Up @@ -97,7 +101,7 @@ jobs:
envsubst < Chart.yaml > Chart-0.yaml
mv Chart-0.yaml Chart.yaml
kubectl config use-context peersyst-privatenet
helm -n fast-auth upgrade ${{ github.event.inputs.environment }} ./ --install --atomic --wait --timeout 301s --values values/${{ github.event.inputs.environment }}.yaml --set-string timestamp=${NOW} --set-string tagRelayer=${{ github.event.inputs.relayer-tag }} --set-string tagAttester=${{ github.event.inputs.attester-tag }} --debug
helm -n fast-auth upgrade ${{ github.event.inputs.environment }} ./ --install --atomic --wait --timeout 301s --values values/${{ github.event.inputs.environment }}.yaml --set-string timestamp=${NOW} --set-string tagRelayer=${{ github.event.inputs.relayer-tag }} --set-string tagAttester=${{ github.event.inputs.attester-tag }} --set-string tagCustomIssuer=${{ github.event.inputs.custom-issuer-tag }} --debug

# Send Slack message if any previous step has failed in this job
- name: 📬 Failure job notification
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,12 @@ jobs:
target: integration
push: false
base_image: ${{ github.sha }}

build-custom-issuer:
needs: [build-base]
uses: ./.github/workflows/build-custom-issuer.yaml
secrets: inherit
with:
target: integration
push: false
base_image: ${{ github.sha }}
37 changes: 37 additions & 0 deletions apps/custom-issuer/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Custom Issuer Service Environment Variables
# Copy this file to .env and update with your actual values

# =============================================================================
# REQUIRED - Application will not start without these
# =============================================================================

# Base64-encoded RSA private key used for signing issued tokens
# To encode a key file: cat signing-key.pem | base64
# Example: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVB...
KEY_BASE64=

# Firebase URL where the validation public key can be retrieved
# Firebase certificate format: https://www.googleapis.com/robot/v1/metadata/x509/{service-account-email}
# Example: https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk@project.iam.gserviceaccount.com
VALIDATION_PUBLIC_KEY_URL=

# Expected issuer URL that incoming JWTs must have in their 'iss' claim
# This should match the issuer URL of the tokens you want to accept
# Example: https://securetoken.google.com/{project-id}
VALIDATION_ISSUER_URL=

# URL of the issuer service (will be included as 'iss' claim in issued tokens)
# Example: http://localhost:3000
ISSUER_URL=

# =============================================================================
# OPTIONAL - Application will use defaults if not set
# =============================================================================

# Port number for the HTTP server (default: 3000)
PORT=3000

# Comma-separated list of allowed CORS origins
# If not set, CORS will be disabled (no cross-origin requests allowed)
# Example: http://localhost:3000,https://example.com,https://app.example.com
ALLOWED_ORIGINS=
11 changes: 11 additions & 0 deletions apps/custom-issuer/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
root: true,
extends: [require.resolve("@shared/eslint/nest")],
rules: {
"jsdoc/require-jsdoc": "off",
"jsdoc/require-param": "off",
"jsdoc/require-returns": "off",
"jsdoc/match-description": "off",
"no-console": "off",
},
};
59 changes: 59 additions & 0 deletions apps/custom-issuer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# compiled output
/dist
/node_modules
/build

# Logs
logs
*.log
npm-debug.log*
pnpm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# OS
.DS_Store

# Tests
/coverage
/.nyc_output

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# temp directory
.temp
.tmp

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Keys
keys/
99 changes: 99 additions & 0 deletions apps/custom-issuer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Custom Issuer Service

A NestJS service that validates incoming JWTs and issues new tokens with a different signing key.

## Quick Start

### 1. Install Dependencies

```bash
pnpm install
```

### 2. Generate Test Keys (Optional)

```bash
# Generate RSA key pair for testing
mkdir -p keys
openssl genrsa -out keys/signing-key.pem 2048
openssl rsa -in keys/signing-key.pem -pubout -out keys/validation-public-key.pem
chmod 600 keys/signing-key.pem
chmod 644 keys/validation-public-key.pem
```

### 3. Configure Environment Variables

Copy `.env.example` to `.env` and fill in the required values:

```bash
cp .env.example .env
```

Required variables:
- `KEY_BASE64` - Base64-encoded RSA private key for signing tokens (encode with: `cat signing-key.pem | base64`)
- `VALIDATION_PUBLIC_KEY_URL` - Firebase URL where the validation public key can be retrieved (e.g., `https://www.googleapis.com/robot/v1/metadata/x509/{service-account-email}`)
- `VALIDATION_ISSUER_URL` - Expected issuer URL that incoming JWTs must have in their `iss` claim (e.g., `https://securetoken.google.com/{project-id}`)
- `ISSUER_URL` - URL of the issuer service (e.g., `http://localhost:3000`)

Optional variables:
- `PORT` - Server port (default: 3000)
- `ALLOWED_ORIGINS` - Comma-separated CORS origins

### 4. Start the Service

```bash
# Development mode (with hot reload)
pnpm start:dev

# Production mode
pnpm build
pnpm start:prod
```

The service will be available at `http://localhost:3000` (or your configured port).

## Usage

### Issue a Token

```bash
POST /issuer/issue
Content-Type: application/json

{
"jwt": "your-validated-jwt-token"
}
```

The service will:
1. Validate the input JWT using the validation public key
2. Extract `sub`, `exp`, and `nbf` claims
3. Issue a new token signed with the signing private key
4. Include the `iss` claim with the issuer URL

### Generate Test JWTs

```bash
# Generate and send a test JWT to the service
pnpm generate:jwt

# Generate with custom options
pnpm generate:jwt -- --sub "user@example.com" --exp 7200
```

## Scripts

- `pnpm start:dev` - Start in development mode with hot reload
- `pnpm build` - Build for production
- `pnpm start:prod` - Start production server
- `pnpm test` - Run tests
- `pnpm generate:jwt` - Generate test JWT tokens

## Security

- Input validation with `class-validator`
- Request size limits (10KB)
- CORS protection
- Path traversal protection for key files
- Sensitive data redaction in error logs
- Rate limiting recommended for production
8 changes: 8 additions & 0 deletions apps/custom-issuer/nest-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true
}
}
Loading
Loading