mirror of
https://github.com/wahyd4/passkey-auth.git
synced 2026-08-09 04:15:55 +10:00
Add helm chart
This commit is contained in:
@@ -0,0 +1,10 @@
|
|||||||
|
# Configuration for chart-releaser
|
||||||
|
# See https://github.com/helm/chart-releaser for more info
|
||||||
|
|
||||||
|
owner: wahyd4
|
||||||
|
git-repo: passkey-auth
|
||||||
|
charts-repo: https://wahyd4.github.io/passkey-auth
|
||||||
|
target-branch: gh-pages
|
||||||
|
package-path: .cr-release-packages
|
||||||
|
index-path: .cr-index
|
||||||
|
skip-existing: true
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
name: Release Helm Chart
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- 'helm/passkey-auth/**'
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "pages"
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Helm
|
||||||
|
uses: azure/setup-helm@v4
|
||||||
|
with:
|
||||||
|
version: '3.14.0'
|
||||||
|
|
||||||
|
- name: Set up chart-testing
|
||||||
|
uses: helm/chart-testing-action@v2.6.1
|
||||||
|
|
||||||
|
- name: Run chart-testing (list)
|
||||||
|
run: ct list --target-branch ${{ github.event.repository.default_branch }} --chart-dirs helm
|
||||||
|
|
||||||
|
- name: Run chart-testing (lint)
|
||||||
|
run: ct lint --target-branch ${{ github.event.repository.default_branch }} --chart-dirs helm
|
||||||
|
|
||||||
|
- name: Create kind cluster
|
||||||
|
uses: helm/kind-action@v1.9.0
|
||||||
|
|
||||||
|
- name: Run chart-testing (install)
|
||||||
|
run: |
|
||||||
|
# Install with test values
|
||||||
|
ct install --target-branch ${{ github.event.repository.default_branch }} --chart-dirs helm \
|
||||||
|
--helm-extra-set-args "--set config.webauthn.rpId=test.local --set config.auth.allowedEmails={test@example.com} --set secrets.sessionSecret=test-secret-for-ci-only --set ingress.enabled=false"
|
||||||
|
|
||||||
|
release:
|
||||||
|
needs: lint-test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.ref == 'refs/heads/main' || github.event_name == 'release'
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Configure Git
|
||||||
|
run: |
|
||||||
|
git config user.name "$GITHUB_ACTOR"
|
||||||
|
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||||
|
|
||||||
|
- name: Install Helm
|
||||||
|
uses: azure/setup-helm@v4
|
||||||
|
with:
|
||||||
|
version: '3.14.0'
|
||||||
|
|
||||||
|
- name: Add helm repos
|
||||||
|
run: |
|
||||||
|
helm repo add bitnami https://charts.bitnami.com/bitnami
|
||||||
|
|
||||||
|
- name: Run chart-releaser
|
||||||
|
uses: helm/chart-releaser-action@v1.6.0
|
||||||
|
with:
|
||||||
|
charts_dir: helm
|
||||||
|
config: .github/cr.yaml
|
||||||
|
env:
|
||||||
|
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
|
||||||
|
- name: Setup Pages
|
||||||
|
uses: actions/configure-pages@v4
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-pages-artifact@v3
|
||||||
|
with:
|
||||||
|
path: .cr-release-packages
|
||||||
|
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v4
|
||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
bin/
|
bin/
|
||||||
passkey-auth
|
./passkey-auth
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|||||||
@@ -0,0 +1,313 @@
|
|||||||
|
# Hosting Passkey Auth Helm Chart on GitHub
|
||||||
|
|
||||||
|
This guide explains how to host your Helm chart on GitHub Pages and make it available via a public Helm repository.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- GitHub repository with your Helm chart
|
||||||
|
- GitHub Actions enabled
|
||||||
|
- GitHub Pages enabled
|
||||||
|
|
||||||
|
## Setup Steps
|
||||||
|
|
||||||
|
### 1. Repository Structure
|
||||||
|
|
||||||
|
Ensure your repository has this structure:
|
||||||
|
```
|
||||||
|
passkey-auth/
|
||||||
|
├── .github/
|
||||||
|
│ ├── workflows/
|
||||||
|
│ │ └── helm-release.yml
|
||||||
|
│ └── cr.yaml
|
||||||
|
├── helm/
|
||||||
|
│ └── passkey-auth/
|
||||||
|
│ ├── Chart.yaml
|
||||||
|
│ ├── values.yaml
|
||||||
|
│ ├── README.md
|
||||||
|
│ ├── templates/
|
||||||
|
│ └── examples/
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Enable GitHub Pages
|
||||||
|
|
||||||
|
1. Go to your GitHub repository
|
||||||
|
2. Navigate to **Settings** > **Pages**
|
||||||
|
3. Under **Source**, select **GitHub Actions**
|
||||||
|
4. Save the configuration
|
||||||
|
|
||||||
|
### 3. Configure Repository Settings
|
||||||
|
|
||||||
|
1. **Enable GitHub Actions**:
|
||||||
|
- Go to **Settings** > **Actions** > **General**
|
||||||
|
- Enable "Allow all actions and reusable workflows"
|
||||||
|
|
||||||
|
2. **Set up GitHub Pages permissions**:
|
||||||
|
- Go to **Settings** > **Actions** > **General**
|
||||||
|
- Under "Workflow permissions", select "Read and write permissions"
|
||||||
|
- Check "Allow GitHub Actions to create and approve pull requests"
|
||||||
|
|
||||||
|
### 4. Update Chart Configuration
|
||||||
|
|
||||||
|
Edit `.github/cr.yaml` to match your repository:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
owner: YOUR_GITHUB_USERNAME # Change this
|
||||||
|
git-repo: passkey-auth # Change if different
|
||||||
|
charts-repo: https://YOUR_GITHUB_USERNAME.github.io/passkey-auth
|
||||||
|
target-branch: gh-pages
|
||||||
|
package-path: .cr-release-packages
|
||||||
|
index-path: .cr-index
|
||||||
|
skip-existing: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Create Your First Release
|
||||||
|
|
||||||
|
1. **Tag your first release**:
|
||||||
|
```bash
|
||||||
|
git tag v0.1.0
|
||||||
|
git push origin v0.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Or push changes to trigger workflow**:
|
||||||
|
```bash
|
||||||
|
git add .
|
||||||
|
git commit -m "Add Helm chart"
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
The GitHub Action will automatically:
|
||||||
|
- Lint and test your chart
|
||||||
|
- Package the chart
|
||||||
|
- Create a GitHub release
|
||||||
|
- Update the Helm repository index
|
||||||
|
- Deploy to GitHub Pages
|
||||||
|
|
||||||
|
### 6. Verify the Setup
|
||||||
|
|
||||||
|
1. **Check GitHub Actions**:
|
||||||
|
- Go to **Actions** tab in your repository
|
||||||
|
- Verify the "Release Helm Chart" workflow completes successfully
|
||||||
|
|
||||||
|
2. **Check GitHub Pages**:
|
||||||
|
- Go to **Settings** > **Pages**
|
||||||
|
- You should see "Your site is published at https://username.github.io/passkey-auth"
|
||||||
|
|
||||||
|
3. **Test the Helm repository**:
|
||||||
|
```bash
|
||||||
|
helm repo add passkey-auth https://YOUR_USERNAME.github.io/passkey-auth
|
||||||
|
helm repo update
|
||||||
|
helm search repo passkey-auth
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using Your Hosted Chart
|
||||||
|
|
||||||
|
### Add the Repository
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo add passkey-auth https://YOUR_USERNAME.github.io/passkey-auth
|
||||||
|
helm repo update
|
||||||
|
```
|
||||||
|
|
||||||
|
### Install the Chart
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Basic installation
|
||||||
|
helm install my-passkey-auth passkey-auth/passkey-auth
|
||||||
|
|
||||||
|
# With custom values
|
||||||
|
helm install my-passkey-auth passkey-auth/passkey-auth \
|
||||||
|
--set config.webauthn.rpId=auth.example.com \
|
||||||
|
--set secrets.sessionSecret="your-secure-secret"
|
||||||
|
|
||||||
|
# With values file
|
||||||
|
helm install my-passkey-auth passkey-auth/passkey-auth \
|
||||||
|
-f values-production.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Search Available Versions
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm search repo passkey-auth --versions
|
||||||
|
```
|
||||||
|
|
||||||
|
## Maintenance and Updates
|
||||||
|
|
||||||
|
### Releasing New Versions
|
||||||
|
|
||||||
|
1. **Update Chart.yaml**:
|
||||||
|
```yaml
|
||||||
|
version: 0.2.0 # Increment version
|
||||||
|
appVersion: "v1.1.0" # Update app version if needed
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Commit and push**:
|
||||||
|
```bash
|
||||||
|
git add helm/passkey-auth/Chart.yaml
|
||||||
|
git commit -m "Bump chart version to 0.2.0"
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **The workflow will automatically**:
|
||||||
|
- Package the new version
|
||||||
|
- Create a GitHub release
|
||||||
|
- Update the Helm repository
|
||||||
|
|
||||||
|
### Testing Charts Locally
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Lint the chart
|
||||||
|
helm lint helm/passkey-auth/
|
||||||
|
|
||||||
|
# Template the chart (dry run)
|
||||||
|
helm template my-passkey-auth helm/passkey-auth/ \
|
||||||
|
--set config.webauthn.rpId=test.local
|
||||||
|
|
||||||
|
# Install locally for testing
|
||||||
|
helm install test-release helm/passkey-auth/ \
|
||||||
|
--dry-run --debug
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Configuration
|
||||||
|
|
||||||
|
### Custom Domain for Helm Repository
|
||||||
|
|
||||||
|
If you want to use a custom domain instead of `username.github.io`:
|
||||||
|
|
||||||
|
1. **Set up custom domain in GitHub Pages**:
|
||||||
|
- Go to **Settings** > **Pages**
|
||||||
|
- Add your custom domain (e.g., `charts.example.com`)
|
||||||
|
|
||||||
|
2. **Update `.github/cr.yaml`**:
|
||||||
|
```yaml
|
||||||
|
charts-repo: https://charts.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Configure DNS**:
|
||||||
|
- Add CNAME record pointing to `username.github.io`
|
||||||
|
|
||||||
|
### Multiple Charts in One Repository
|
||||||
|
|
||||||
|
If you have multiple charts:
|
||||||
|
|
||||||
|
```
|
||||||
|
helm/
|
||||||
|
├── passkey-auth/
|
||||||
|
│ ├── Chart.yaml
|
||||||
|
│ └── ...
|
||||||
|
├── another-chart/
|
||||||
|
│ ├── Chart.yaml
|
||||||
|
│ └── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
The workflow will automatically detect and release all charts.
|
||||||
|
|
||||||
|
### Private Repositories
|
||||||
|
|
||||||
|
For private repositories, users will need:
|
||||||
|
|
||||||
|
1. **GitHub Personal Access Token**:
|
||||||
|
```bash
|
||||||
|
helm repo add passkey-auth https://username:TOKEN@username.github.io/passkey-auth
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Or configure helm with auth**:
|
||||||
|
```bash
|
||||||
|
helm repo add passkey-auth https://username.github.io/passkey-auth \
|
||||||
|
--username YOUR_USERNAME \
|
||||||
|
--password YOUR_TOKEN
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **GitHub Actions Fails**:
|
||||||
|
- Check workflow permissions in repository settings
|
||||||
|
- Verify GitHub Pages is enabled
|
||||||
|
- Check if there are syntax errors in the chart
|
||||||
|
|
||||||
|
2. **Chart Not Found**:
|
||||||
|
- Verify the repository URL is correct
|
||||||
|
- Check if GitHub Pages deployment completed
|
||||||
|
- Ensure chart name matches directory name
|
||||||
|
|
||||||
|
3. **Permission Denied**:
|
||||||
|
- Verify GitHub Actions has write permissions
|
||||||
|
- Check if GitHub Pages is enabled for the repository
|
||||||
|
|
||||||
|
### Debug Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check repository status
|
||||||
|
helm repo list
|
||||||
|
|
||||||
|
# Update repositories
|
||||||
|
helm repo update
|
||||||
|
|
||||||
|
# Debug template rendering
|
||||||
|
helm template my-release helm/passkey-auth/ --debug
|
||||||
|
|
||||||
|
# Validate chart
|
||||||
|
helm lint helm/passkey-auth/
|
||||||
|
|
||||||
|
# Check chart dependencies
|
||||||
|
helm dependency list helm/passkey-auth/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
### Repository Security
|
||||||
|
|
||||||
|
1. **Secrets Management**:
|
||||||
|
- Never commit sensitive values to the repository
|
||||||
|
- Use GitHub Secrets for sensitive configuration
|
||||||
|
- Document security requirements in README
|
||||||
|
|
||||||
|
2. **Chart Signing** (Optional):
|
||||||
|
```bash
|
||||||
|
# Generate GPG key for chart signing
|
||||||
|
gpg --gen-key
|
||||||
|
|
||||||
|
# Export public key
|
||||||
|
gpg --armor --export your-email@example.com > public.key
|
||||||
|
|
||||||
|
# Add to chart-releaser config
|
||||||
|
echo "sign: true" >> .github/cr.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Dependency Security**:
|
||||||
|
- Regularly update chart dependencies
|
||||||
|
- Use dependency vulnerability scanning
|
||||||
|
- Pin specific versions in production
|
||||||
|
|
||||||
|
### Best Practices
|
||||||
|
|
||||||
|
1. **Version Management**:
|
||||||
|
- Follow semantic versioning
|
||||||
|
- Update `appVersion` when application changes
|
||||||
|
- Update `version` when chart changes
|
||||||
|
|
||||||
|
2. **Documentation**:
|
||||||
|
- Keep README.md updated
|
||||||
|
- Document breaking changes
|
||||||
|
- Provide migration guides
|
||||||
|
|
||||||
|
3. **Testing**:
|
||||||
|
- Test charts before releasing
|
||||||
|
- Use CI/CD for automated testing
|
||||||
|
- Validate on different Kubernetes versions
|
||||||
|
|
||||||
|
## Example Repository
|
||||||
|
|
||||||
|
You can see a complete example at: `https://github.com/YOUR_USERNAME/passkey-auth`
|
||||||
|
|
||||||
|
The hosted Helm repository will be available at: `https://YOUR_USERNAME.github.io/passkey-auth`
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
If you encounter issues:
|
||||||
|
1. Check the GitHub Actions logs
|
||||||
|
2. Verify chart syntax with `helm lint`
|
||||||
|
3. Review GitHub Pages deployment status
|
||||||
|
4. Open an issue in the repository for help
|
||||||
@@ -20,13 +20,38 @@ A WebAuthn-based passkey authentication provider that integrates ingress control
|
|||||||
|
|
||||||
## 🚀 Quick Start
|
## 🚀 Quick Start
|
||||||
|
|
||||||
### 1. Build and Test Locally
|
### Using Helm Chart (Recommended)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone <repository-url>
|
# Add the Helm repository
|
||||||
cd passkey-auth
|
helm repo add passkey-auth https://wahyd4.github.io/passkey-auth
|
||||||
|
helm repo update
|
||||||
|
|
||||||
docker-compose up
|
# Install with your configuration
|
||||||
|
helm install my-passkey-auth passkey-auth/passkey-auth \
|
||||||
|
--set config.webauthn.rpId=auth.example.com \
|
||||||
|
--set config.webauthn.rpOrigins="{https://auth.example.com}" \
|
||||||
|
--set config.cors.allowedOrigins="{https://*.example.com}" \
|
||||||
|
--set config.auth.cookieDomain=".example.com" \
|
||||||
|
--set config.auth.allowedEmails="{admin@example.com}" \
|
||||||
|
--set ingress.hosts[0].host=auth.example.com \
|
||||||
|
--set secrets.sessionSecret="your-secure-random-secret-key"
|
||||||
|
|
||||||
|
# Or use a values file
|
||||||
|
helm install my-passkey-auth passkey-auth/passkey-auth -f values-production.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Helm Chart README](helm/passkey-auth/README.md) for detailed configuration options.
|
||||||
|
|
||||||
|
|
||||||
|
### Option 3: Local Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install dependencies and run locally
|
||||||
|
go mod download
|
||||||
|
go run main.go
|
||||||
|
|
||||||
|
# Access at http://localhost:8080
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Configure
|
### 2. Configure
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: passkey-auth
|
||||||
|
description: A WebAuthn-based passkey authentication provider for Kubernetes Nginx Ingress
|
||||||
|
type: application
|
||||||
|
version: 0.1.0
|
||||||
|
appVersion: "main"
|
||||||
|
home: https://github.com/wahyd4/passkey-auth
|
||||||
|
sources:
|
||||||
|
- https://github.com/wahyd4/passkey-auth
|
||||||
|
maintainers:
|
||||||
|
- name: Junwei Zhao
|
||||||
|
email: wahyd4@gmail.com
|
||||||
|
keywords:
|
||||||
|
- authentication
|
||||||
|
- webauthn
|
||||||
|
- passkey
|
||||||
|
- nginx-ingress
|
||||||
|
- security
|
||||||
|
annotations:
|
||||||
|
category: Security
|
||||||
|
licenses: Apache-2.0
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
# Passkey Auth Helm Chart
|
||||||
|
|
||||||
|
A Helm chart for deploying Passkey Auth, a WebAuthn-based passkey authentication provider that integrates with Kubernetes Nginx Ingress controller.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This chart deploys a secure, passwordless authentication service using WebAuthn/FIDO2 passkeys. It's designed to work as an authentication backend for nginx ingress controllers, providing enterprise-grade security without the complexity of traditional password-based systems.
|
||||||
|
|
||||||
|
## TL;DR
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo add passkey-auth https://your-github-username.github.io/passkey-auth-helm
|
||||||
|
helm repo update
|
||||||
|
helm install my-passkey-auth passkey-auth/passkey-auth \
|
||||||
|
--set config.webauthn.rpId=auth.example.com \
|
||||||
|
--set config.webauthn.rpOrigins="{https://auth.example.com}" \
|
||||||
|
--set secrets.sessionSecret="your-very-long-random-secret-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Kubernetes 1.19+
|
||||||
|
- Helm 3.0+
|
||||||
|
- Nginx Ingress Controller
|
||||||
|
- Cert-Manager (for TLS certificates)
|
||||||
|
- StorageClass for persistent volumes
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Add Helm Repository
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo add passkey-auth https://your-github-username.github.io/passkey-auth-helm
|
||||||
|
helm repo update
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Install from Local Chart
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/wahyd4/passkey-auth.git
|
||||||
|
cd passkey-auth
|
||||||
|
helm install my-passkey-auth ./helm/passkey-auth \
|
||||||
|
--values ./helm/passkey-auth/values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
The command deploys Passkey Auth on the Kubernetes cluster with the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation.
|
||||||
|
|
||||||
|
> **Tip**: List all releases using `helm list`
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Core Configuration
|
||||||
|
|
||||||
|
The chart can be configured using the `values.yaml` file or by passing values via `--set` flags.
|
||||||
|
|
||||||
|
#### Required Configuration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
config:
|
||||||
|
webauthn:
|
||||||
|
rpId: "auth.example.com" # Your authentication domain
|
||||||
|
rpOrigins:
|
||||||
|
- "https://auth.example.com" # Allowed origins for WebAuthn
|
||||||
|
|
||||||
|
cors:
|
||||||
|
allowedOrigins:
|
||||||
|
- "https://*.example.com" # CORS allowed origins
|
||||||
|
|
||||||
|
auth:
|
||||||
|
cookieDomain: ".example.com" # Cookie domain for SSO
|
||||||
|
allowedEmails:
|
||||||
|
- "admin@example.com" # Allowed user emails
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
sessionSecret: "your-secure-random-secret" # Session signing secret
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
hosts:
|
||||||
|
- host: auth.example.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Setup Authentication for Your Services
|
||||||
|
|
||||||
|
Add these annotations to your ingress resources to protect them with passkey authentication:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: my-protected-app
|
||||||
|
annotations:
|
||||||
|
nginx.ingress.kubernetes.io/auth-url: "https://auth.example.com/auth"
|
||||||
|
nginx.ingress.kubernetes.io/auth-signin: "https://auth.example.com/login?rd=$scheme://$http_host$request_uri"
|
||||||
|
nginx.ingress.kubernetes.io/auth-response-headers: "X-Auth-User,X-Auth-Email"
|
||||||
|
spec:
|
||||||
|
# ... your ingress spec
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Configuration
|
||||||
|
|
||||||
|
### Custom Storage
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
existingClaim: "my-existing-pvc"
|
||||||
|
storageClass: "ssd-encrypted"
|
||||||
|
size: 10Gi
|
||||||
|
```
|
||||||
|
|
||||||
|
### External Secrets
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: external-secrets
|
||||||
|
|
||||||
|
secrets: {} # Don't create internal secret
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
### Common parameters
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| ------------------- | ---------------------------------------------------------------------------------------- | ----- |
|
||||||
|
| `nameOverride` | String to partially override passkey-auth.fullname template | `""` |
|
||||||
|
| `fullnameOverride` | String to fully override passkey-auth.fullname template | `""` |
|
||||||
|
| `commonLabels` | Add labels to all the deployed resources | `{}` |
|
||||||
|
| `commonAnnotations` | Add annotations to all the deployed resources | `{}` |
|
||||||
|
|
||||||
|
### Passkey Auth parameters
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| ----------------------------- | --------------------------------------------------------------- | ---------------------------------- |
|
||||||
|
| `replicaCount` | Number of Passkey Auth replicas to deploy | `1` |
|
||||||
|
| `image.repository` | Passkey Auth image repository | `ghcr.io/wahyd4/passkey-auth` |
|
||||||
|
| `image.tag` | Passkey Auth image tag (immutable tags are recommended) | `main` |
|
||||||
|
| `image.pullPolicy` | Passkey Auth image pull policy | `Always` |
|
||||||
|
| `image.pullSecrets` | Passkey Auth image pull secrets | `[]` |
|
||||||
|
|
||||||
|
### WebAuthn configuration
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| --------------------------------- | --------------------------------------------------------------- | ------------------------------ |
|
||||||
|
| `config.webauthn.rpDisplayName` | WebAuthn Relying Party display name | `Passkey Auth` |
|
||||||
|
| `config.webauthn.rpId` | WebAuthn Relying Party ID (must match your domain) | `pass.example.com` |
|
||||||
|
| `config.webauthn.rpOrigins` | Allowed origins for WebAuthn (array) | `["https://pass.example.com"]` |
|
||||||
|
|
||||||
|
### CORS configuration
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| --------------------------------- | --------------------------------------------------------------- | -------------------------------- |
|
||||||
|
| `config.cors.allowedOrigins` | CORS allowed origins (array) | `["https://*.example.com"]` |
|
||||||
|
|
||||||
|
### Authentication configuration
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| --------------------------------- | --------------------------------------------------------------- | ------------------------------ |
|
||||||
|
| `config.auth.requireApproval` | Require admin approval for new user registrations | `true` |
|
||||||
|
| `config.auth.cookieDomain` | Cookie domain for SSO (e.g., .example.com) | `.example.com` |
|
||||||
|
| `config.auth.allowedEmails` | List of allowed email addresses (array) | `["admin@example.com"]` |
|
||||||
|
| `config.auth.allowedDomains` | List of allowed email domains (array) | `[]` |
|
||||||
|
|
||||||
|
### Service configuration
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| -------------- | ----------------------------------- | ----------- |
|
||||||
|
| `service.type` | Kubernetes service type | `ClusterIP` |
|
||||||
|
| `service.port` | Kubernetes service port | `80` |
|
||||||
|
|
||||||
|
### Ingress configuration
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| -------------------------- | --------------------------------------------------------------- | ------------------------------ |
|
||||||
|
| `ingress.enabled` | Enable ingress controller resource | `true` |
|
||||||
|
| `ingress.className` | IngressClass that will be used to implement the Ingress | `nginx` |
|
||||||
|
| `ingress.annotations` | Additional annotations for the Ingress resource | `{}` |
|
||||||
|
| `ingress.hosts[0].host` | Hostname for the ingress | `pass.example.com` |
|
||||||
|
| `ingress.hosts[0].paths` | Paths for the ingress | `[{path: "/", pathType: "Prefix"}]` |
|
||||||
|
| `ingress.tls` | TLS configuration for ingress | `[]` |
|
||||||
|
|
||||||
|
### Persistence configuration
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| ----------------------------- | --------------------------------------------------------------- | ------------------ |
|
||||||
|
| `persistence.enabled` | Enable persistent volume for data storage | `true` |
|
||||||
|
| `persistence.storageClass` | Persistent Volume storage class | `""` |
|
||||||
|
| `persistence.accessMode` | Persistent Volume access mode | `ReadWriteOnce` |
|
||||||
|
| `persistence.size` | Persistent Volume size | `2Gi` |
|
||||||
|
| `persistence.existingClaim` | Use existing persistent volume claim | `""` |
|
||||||
|
|
||||||
|
### Security configuration
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| ------------------------------------------------- | --------------------------------------------------------------- | ---------------------------------------------- |
|
||||||
|
| `secrets.sessionSecret` | Session secret for signing cookies (change in production!) | `change-me-in-production-use-long-random-string` |
|
||||||
|
| `podSecurityContext.fsGroup` | Group ID for the pods | `1000` |
|
||||||
|
| `securityContext.allowPrivilegeEscalation` | Allow privilege escalation for containers | `false` |
|
||||||
|
| `securityContext.runAsNonRoot` | Run containers as non-root user | `true` |
|
||||||
|
| `securityContext.runAsUser` | User ID for the containers | `1000` |
|
||||||
|
| `securityContext.capabilities.drop` | Dropped capabilities | `["ALL"]` |
|
||||||
|
|
||||||
|
### Resource management
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| ----------------------------- | --------------------------------------------------------------- | -------- |
|
||||||
|
| `resources.limits.cpu` | CPU resource limits | `400m` |
|
||||||
|
| `resources.limits.memory` | Memory resource limits | `512Mi` |
|
||||||
|
| `resources.requests.cpu` | CPU resource requests | `100m` |
|
||||||
|
| `resources.requests.memory` | Memory resource requests | `128Mi` |
|
||||||
|
|
||||||
|
### Autoscaling configuration
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| -------------------------------------------------- | --------------------------------------------------------------- | ------- |
|
||||||
|
| `autoscaling.enabled` | Enable Horizontal Pod Autoscaler | `false` |
|
||||||
|
| `autoscaling.minReplicas` | Minimum number of replicas | `1` |
|
||||||
|
| `autoscaling.maxReplicas` | Maximum number of replicas | `3` |
|
||||||
|
| `autoscaling.targetCPUUtilizationPercentage` | Target CPU utilization percentage | `80` |
|
||||||
|
| `autoscaling.targetMemoryUtilizationPercentage` | Target memory utilization percentage | `""` |
|
||||||
|
|
||||||
|
### Environment variables
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| ---------------- | --------------------------------------------------------------- | ------- |
|
||||||
|
| `env.CONFIG_PATH` | Path to the configuration file | `/app/config.yaml` |
|
||||||
|
| `env.ADMIN_EMAIL` | Admin email for auto-approval (optional) | `""` |
|
||||||
|
| `env.DEFAULT_EMAIL` | Default email for initial setup (optional) | `""` |
|
||||||
|
|
||||||
|
### Other parameters
|
||||||
|
|
||||||
|
| Name | Description | Value |
|
||||||
|
| ------------- | --------------------------------------------------------------- | ------- |
|
||||||
|
| `nodeSelector` | Node labels for pod assignment | `{}` |
|
||||||
|
| `tolerations` | Tolerations for pod assignment | `[]` |
|
||||||
|
| `affinity` | Affinity for pod assignment | `{}` |
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# Development values for passkey-auth
|
||||||
|
# Use this for local development and testing
|
||||||
|
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/wahyd4/passkey-auth
|
||||||
|
tag: "main"
|
||||||
|
pullPolicy: Always
|
||||||
|
|
||||||
|
# Application configuration
|
||||||
|
config:
|
||||||
|
webauthn:
|
||||||
|
rpDisplayName: "Dev Passkey Auth"
|
||||||
|
rpId: "localhost"
|
||||||
|
rpOrigins:
|
||||||
|
- "http://localhost:8080"
|
||||||
|
- "https://auth.dev.local"
|
||||||
|
|
||||||
|
cors:
|
||||||
|
allowedOrigins:
|
||||||
|
- "*" # Allow all origins in dev
|
||||||
|
|
||||||
|
auth:
|
||||||
|
requireApproval: false # Auto-approve in dev
|
||||||
|
cookieDomain: ".dev.local"
|
||||||
|
allowedEmails: [] # Allow any email in dev
|
||||||
|
|
||||||
|
# Security configuration (dev only)
|
||||||
|
secrets:
|
||||||
|
sessionSecret: "dev-secret-not-for-production"
|
||||||
|
|
||||||
|
# Disable ingress for local development
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Minimal persistence for dev
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
size: 1Gi
|
||||||
|
|
||||||
|
# Minimal resources for dev
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 256Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
|
||||||
|
# Disable autoscaling
|
||||||
|
autoscaling:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
env:
|
||||||
|
- name: DEFAULT_EMAIL
|
||||||
|
value: "dev@example.com"
|
||||||
|
- name: CONFIG_PATH
|
||||||
|
value: "/app/config.yaml"
|
||||||
|
- name: ADMIN_EMAIL
|
||||||
|
value: "dev@example.com"
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
# Production values for passkey-auth
|
||||||
|
# Use this as a template for production deployments
|
||||||
|
|
||||||
|
replicaCount: 2
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/wahyd4/passkey-auth
|
||||||
|
tag: "v1.0.0" # Pin to specific version in production
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
# Application configuration
|
||||||
|
config:
|
||||||
|
webauthn:
|
||||||
|
rpDisplayName: "My Company Passkey Auth"
|
||||||
|
rpId: "auth.company.com" # CHANGE THIS
|
||||||
|
rpOrigins:
|
||||||
|
- "https://auth.company.com" # CHANGE THIS
|
||||||
|
|
||||||
|
cors:
|
||||||
|
allowedOrigins:
|
||||||
|
- "https://*.company.com" # CHANGE THIS
|
||||||
|
- "https://app.company.com" # Add specific origins
|
||||||
|
|
||||||
|
auth:
|
||||||
|
requireApproval: true
|
||||||
|
cookieDomain: ".company.com" # CHANGE THIS
|
||||||
|
allowedEmails:
|
||||||
|
- "admin@company.com" # CHANGE THIS
|
||||||
|
- "user@company.com" # Add allowed users
|
||||||
|
|
||||||
|
# Security configuration
|
||||||
|
secrets:
|
||||||
|
sessionSecret: "" # REQUIRED: Set this to a secure random string (32+ chars)
|
||||||
|
|
||||||
|
# Ingress configuration
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: "nginx"
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||||
|
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||||
|
hosts:
|
||||||
|
- host: auth.company.com # CHANGE THIS
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
tls:
|
||||||
|
- secretName: auth-company-com-tls
|
||||||
|
hosts:
|
||||||
|
- auth.company.com # CHANGE THIS
|
||||||
|
|
||||||
|
# Persistence configuration
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
storageClass: "fast-ssd" # Use fast storage for production
|
||||||
|
size: 5Gi
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
|
||||||
|
# Resource configuration
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 1Gi
|
||||||
|
requests:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 256Mi
|
||||||
|
|
||||||
|
# Autoscaling configuration
|
||||||
|
autoscaling:
|
||||||
|
enabled: true
|
||||||
|
minReplicas: 2
|
||||||
|
maxReplicas: 5
|
||||||
|
targetCPUUtilizationPercentage: 70
|
||||||
|
|
||||||
|
# Health checks
|
||||||
|
healthCheck:
|
||||||
|
enabled: true
|
||||||
|
livenessProbe:
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 30
|
||||||
|
timeoutSeconds: 10
|
||||||
|
failureThreshold: 3
|
||||||
|
readinessProbe:
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
|
||||||
|
# Security context
|
||||||
|
podSecurityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
runAsNonRoot: true
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false # SQLite needs write access
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
|
||||||
|
# Node selection
|
||||||
|
nodeSelector:
|
||||||
|
kubernetes.io/os: linux
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
env:
|
||||||
|
- name: DEFAULT_EMAIL
|
||||||
|
value: "admin@company.com" # CHANGE THIS
|
||||||
|
- name: CONFIG_PATH
|
||||||
|
value: "/app/config.yaml"
|
||||||
|
- name: ADMIN_EMAIL
|
||||||
|
value: "admin@company.com" # CHANGE THIS
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
1. Get the application URL by running these commands:
|
||||||
|
{{- if .Values.ingress.enabled }}
|
||||||
|
{{- range $host := .Values.ingress.hosts }}
|
||||||
|
{{- range .paths }}
|
||||||
|
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else if contains "NodePort" .Values.service.type }}
|
||||||
|
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "passkey-auth.fullname" . }})
|
||||||
|
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||||
|
echo http://$NODE_IP:$NODE_PORT
|
||||||
|
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||||
|
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||||
|
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "passkey-auth.fullname" . }}'
|
||||||
|
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "passkey-auth.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||||
|
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||||
|
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||||
|
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "passkey-auth.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||||
|
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
||||||
|
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||||
|
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
2. Configure your ingress for authentication by adding these annotations to your protected services:
|
||||||
|
|
||||||
|
annotations:
|
||||||
|
nginx.ingress.kubernetes.io/auth-url: "http{{ if .Values.ingress.tls }}s{{ end }}://{{ (index .Values.ingress.hosts 0).host }}/auth"
|
||||||
|
nginx.ingress.kubernetes.io/auth-signin: "http{{ if .Values.ingress.tls }}s{{ end }}://{{ (index .Values.ingress.hosts 0).host }}/login?rd=$scheme://$http_host$request_uri"
|
||||||
|
nginx.ingress.kubernetes.io/auth-response-headers: "X-Auth-User,X-Auth-Email"
|
||||||
|
|
||||||
|
3. Visit the admin panel to manage users:
|
||||||
|
{{- if .Values.ingress.enabled }}
|
||||||
|
http{{ if .Values.ingress.tls }}s{{ end }}://{{ (index .Values.ingress.hosts 0).host }}/admin
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
Important Security Notes:
|
||||||
|
- Change the default session secret in values.yaml before deploying to production
|
||||||
|
- Configure proper CORS origins for your domain
|
||||||
|
- Set up proper TLS certificates
|
||||||
|
- Review and configure allowed email addresses
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
{{/*
|
||||||
|
Expand the name of the chart.
|
||||||
|
*/}}
|
||||||
|
{{- define "passkey-auth.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create a default fully qualified app name.
|
||||||
|
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||||
|
If release name contains chart name it will be used as a full name.
|
||||||
|
*/}}
|
||||||
|
{{- define "passkey-auth.fullname" -}}
|
||||||
|
{{- if .Values.fullnameOverride }}
|
||||||
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||||
|
{{- if contains $name .Release.Name }}
|
||||||
|
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create chart name and version as used by the chart label.
|
||||||
|
*/}}
|
||||||
|
{{- define "passkey-auth.chart" -}}
|
||||||
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Common labels
|
||||||
|
*/}}
|
||||||
|
{{- define "passkey-auth.labels" -}}
|
||||||
|
helm.sh/chart: {{ include "passkey-auth.chart" . }}
|
||||||
|
{{ include "passkey-auth.selectorLabels" . }}
|
||||||
|
{{- if .Chart.AppVersion }}
|
||||||
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
{{- end }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Selector labels
|
||||||
|
*/}}
|
||||||
|
{{- define "passkey-auth.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "passkey-auth.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create the name of the service account to use
|
||||||
|
*/}}
|
||||||
|
{{- define "passkey-auth.serviceAccountName" -}}
|
||||||
|
{{- if .Values.serviceAccount.create }}
|
||||||
|
{{- default (include "passkey-auth.fullname" .) .Values.serviceAccount.name }}
|
||||||
|
{{- else }}
|
||||||
|
{{- default "default" .Values.serviceAccount.name }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create the name of the configmap
|
||||||
|
*/}}
|
||||||
|
{{- define "passkey-auth.configmapName" -}}
|
||||||
|
{{- printf "%s-config" (include "passkey-auth.fullname" .) }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create the name of the secret
|
||||||
|
*/}}
|
||||||
|
{{- define "passkey-auth.secretName" -}}
|
||||||
|
{{- printf "%s-secrets" (include "passkey-auth.fullname" .) }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create the name of the PVC
|
||||||
|
*/}}
|
||||||
|
{{- define "passkey-auth.pvcName" -}}
|
||||||
|
{{- if .Values.persistence.existingClaim }}
|
||||||
|
{{- .Values.persistence.existingClaim }}
|
||||||
|
{{- else }}
|
||||||
|
{{- printf "%s-pvc" (include "passkey-auth.fullname" .) }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ include "passkey-auth.configmapName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "passkey-auth.labels" . | nindent 4 }}
|
||||||
|
data:
|
||||||
|
config.yaml: |
|
||||||
|
server:
|
||||||
|
port: {{ .Values.config.server.port | quote }}
|
||||||
|
host: {{ .Values.config.server.host | quote }}
|
||||||
|
|
||||||
|
webauthn:
|
||||||
|
rp_display_name: {{ .Values.config.webauthn.rpDisplayName | quote }}
|
||||||
|
rp_id: {{ .Values.config.webauthn.rpId | quote }}
|
||||||
|
rp_origins:
|
||||||
|
{{- range .Values.config.webauthn.rpOrigins }}
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
database:
|
||||||
|
path: {{ .Values.config.database.path | quote }}
|
||||||
|
|
||||||
|
cors:
|
||||||
|
allowed_origins:
|
||||||
|
{{- range .Values.config.cors.allowedOrigins }}
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
auth:
|
||||||
|
require_approval: {{ .Values.config.auth.requireApproval }}
|
||||||
|
cookie_domain: {{ .Values.config.auth.cookieDomain | quote }}
|
||||||
|
{{- if .Values.config.auth.allowedEmails }}
|
||||||
|
allowed_emails:
|
||||||
|
{{- range .Values.config.auth.allowedEmails }}
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "passkey-auth.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "passkey-auth.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
{{- if not .Values.autoscaling.enabled }}
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
{{- end }}
|
||||||
|
revisionHistoryLimit: 3
|
||||||
|
strategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "passkey-auth.selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
{{- with .Values.podAnnotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "passkey-auth.selectorLabels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
serviceAccountName: {{ include "passkey-auth.serviceAccountName" . }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: {{ .Values.service.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
{{- range .Values.env }}
|
||||||
|
- name: {{ .name }}
|
||||||
|
value: {{ .value | quote }}
|
||||||
|
{{- end }}
|
||||||
|
- name: SESSION_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "passkey-auth.secretName" . }}
|
||||||
|
key: session-secret
|
||||||
|
{{- with .Values.envFrom }}
|
||||||
|
envFrom:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: "/app/config.yaml"
|
||||||
|
subPath: config.yaml
|
||||||
|
readOnly: true
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.volumeMounts }}
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.healthCheck.enabled }}
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: {{ .Values.healthCheck.path }}
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: {{ .Values.healthCheck.livenessProbe.initialDelaySeconds }}
|
||||||
|
periodSeconds: {{ .Values.healthCheck.livenessProbe.periodSeconds }}
|
||||||
|
timeoutSeconds: {{ .Values.healthCheck.livenessProbe.timeoutSeconds }}
|
||||||
|
failureThreshold: {{ .Values.healthCheck.livenessProbe.failureThreshold }}
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: {{ .Values.healthCheck.path }}
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: {{ .Values.healthCheck.readinessProbe.initialDelaySeconds }}
|
||||||
|
periodSeconds: {{ .Values.healthCheck.readinessProbe.periodSeconds }}
|
||||||
|
timeoutSeconds: {{ .Values.healthCheck.readinessProbe.timeoutSeconds }}
|
||||||
|
failureThreshold: {{ .Values.healthCheck.readinessProbe.failureThreshold }}
|
||||||
|
startupProbe:
|
||||||
|
httpGet:
|
||||||
|
path: {{ .Values.healthCheck.path }}
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: {{ .Values.healthCheck.startupProbe.initialDelaySeconds }}
|
||||||
|
periodSeconds: {{ .Values.healthCheck.startupProbe.periodSeconds }}
|
||||||
|
timeoutSeconds: {{ .Values.healthCheck.startupProbe.timeoutSeconds }}
|
||||||
|
failureThreshold: {{ .Values.healthCheck.startupProbe.failureThreshold }}
|
||||||
|
{{- end }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: {{ include "passkey-auth.configmapName" . }}
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ include "passkey-auth.pvcName" . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.volumes }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
restartPolicy: Always
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
{{- if .Values.autoscaling.enabled }}
|
||||||
|
apiVersion: autoscaling/v2
|
||||||
|
kind: HorizontalPodAutoscaler
|
||||||
|
metadata:
|
||||||
|
name: {{ include "passkey-auth.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "passkey-auth.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
scaleTargetRef:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: {{ include "passkey-auth.fullname" . }}
|
||||||
|
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||||
|
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||||
|
metrics:
|
||||||
|
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||||
|
- type: Resource
|
||||||
|
resource:
|
||||||
|
name: cpu
|
||||||
|
target:
|
||||||
|
type: Utilization
|
||||||
|
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||||
|
- type: Resource
|
||||||
|
resource:
|
||||||
|
name: memory
|
||||||
|
target:
|
||||||
|
type: Utilization
|
||||||
|
averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
{{- if .Values.ingress.enabled -}}
|
||||||
|
{{- $fullName := include "passkey-auth.fullname" . -}}
|
||||||
|
{{- $svcPort := .Values.service.port -}}
|
||||||
|
{{- if and .Values.ingress.className (not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class")) }}
|
||||||
|
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
|
||||||
|
{{- end }}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ $fullName }}
|
||||||
|
labels:
|
||||||
|
{{- include "passkey-auth.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.ingress.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- if not (hasKey . "nginx.ingress.kubernetes.io/upstream-vhost") }}
|
||||||
|
nginx.ingress.kubernetes.io/upstream-vhost: {{ $.Values.config.webauthn.rpId | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||||
|
ingressClassName: {{ .Values.ingress.className }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.ingress.tls }}
|
||||||
|
tls:
|
||||||
|
{{- range .Values.ingress.tls }}
|
||||||
|
- hosts:
|
||||||
|
{{- range .hosts }}
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
secretName: {{ .secretName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
{{- range .Values.ingress.hosts }}
|
||||||
|
- host: {{ .host | quote }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
{{- range .paths }}
|
||||||
|
- path: {{ .path }}
|
||||||
|
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
|
||||||
|
pathType: {{ .pathType }}
|
||||||
|
{{- end }}
|
||||||
|
backend:
|
||||||
|
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||||
|
service:
|
||||||
|
name: {{ $fullName }}
|
||||||
|
port:
|
||||||
|
number: {{ $svcPort }}
|
||||||
|
{{- else }}
|
||||||
|
serviceName: {{ $fullName }}
|
||||||
|
servicePort: {{ $svcPort }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
{{- if not .Values.persistence.existingClaim }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: {{ include "passkey-auth.pvcName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "passkey-auth.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.accessMode }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.size }}
|
||||||
|
{{- if .Values.persistence.storageClass }}
|
||||||
|
storageClassName: {{ .Values.persistence.storageClass }}
|
||||||
|
{{- end }}
|
||||||
|
volumeMode: Filesystem
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ include "passkey-auth.secretName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "passkey-auth.labels" . | nindent 4 }}
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
session-secret: {{ .Values.secrets.sessionSecret | b64enc | quote }}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "passkey-auth.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "passkey-auth.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.type }}
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.service.port }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
{{- include "passkey-auth.selectorLabels" . | nindent 4 }}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{{- if .Values.serviceAccount.create -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: {{ include "passkey-auth.serviceAccountName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "passkey-auth.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.serviceAccount.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
# Default values for passkey-auth.
|
||||||
|
# This is a YAML-formatted file.
|
||||||
|
# Declare variables to be passed into your templates.
|
||||||
|
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/wahyd4/passkey-auth
|
||||||
|
pullPolicy: Always
|
||||||
|
# Overrides the image tag whose default is the chart appVersion.
|
||||||
|
tag: "main"
|
||||||
|
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: github-image-pull-secret
|
||||||
|
|
||||||
|
nameOverride: ""
|
||||||
|
fullnameOverride: ""
|
||||||
|
|
||||||
|
serviceAccount:
|
||||||
|
# Specifies whether a service account should be created
|
||||||
|
create: false
|
||||||
|
# Annotations to add to the service account
|
||||||
|
annotations: {}
|
||||||
|
# The name of the service account to use.
|
||||||
|
# If not set and create is true, a name is generated using the fullname template
|
||||||
|
name: ""
|
||||||
|
|
||||||
|
podAnnotations: {}
|
||||||
|
|
||||||
|
podSecurityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
# readOnlyRootFilesystem: true
|
||||||
|
# runAsNonRoot: true
|
||||||
|
# runAsUser: 1000
|
||||||
|
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: "nginx"
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/tls-acme: "true"
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-set-headers: "passkey-auth-headers"
|
||||||
|
nginx.ingress.kubernetes.io/upstream-vhost: "" # Will be set to config.webauthn.rpId
|
||||||
|
nginx.ingress.kubernetes.io/proxy-redirect-from: "http://"
|
||||||
|
nginx.ingress.kubernetes.io/proxy-redirect-to: "https://"
|
||||||
|
hosts:
|
||||||
|
- host: pass.example.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
tls:
|
||||||
|
- secretName: passkey-auth-tls
|
||||||
|
hosts:
|
||||||
|
- pass.example.com
|
||||||
|
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 400m
|
||||||
|
memory: 512Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
|
||||||
|
autoscaling:
|
||||||
|
enabled: false
|
||||||
|
minReplicas: 1
|
||||||
|
maxReplicas: 3
|
||||||
|
targetCPUUtilizationPercentage: 80
|
||||||
|
# targetMemoryUtilizationPercentage: 80
|
||||||
|
|
||||||
|
nodeSelector: {}
|
||||||
|
|
||||||
|
tolerations: []
|
||||||
|
|
||||||
|
affinity: {}
|
||||||
|
|
||||||
|
# Persistent storage for SQLite database
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
storageClass: "" # Use default storage class
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 2Gi
|
||||||
|
# existingClaim: ""
|
||||||
|
|
||||||
|
# Health check configuration
|
||||||
|
healthCheck:
|
||||||
|
enabled: true
|
||||||
|
path: /health
|
||||||
|
livenessProbe:
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
readinessProbe:
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 3
|
||||||
|
startupProbe:
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 3
|
||||||
|
failureThreshold: 6
|
||||||
|
|
||||||
|
# Application configuration
|
||||||
|
config:
|
||||||
|
server:
|
||||||
|
port: "8080"
|
||||||
|
host: "0.0.0.0"
|
||||||
|
|
||||||
|
webauthn:
|
||||||
|
rpDisplayName: "Passkey Auth"
|
||||||
|
rpId: "pass.example.com"
|
||||||
|
rpOrigins:
|
||||||
|
- "https://pass.example.com"
|
||||||
|
|
||||||
|
database:
|
||||||
|
path: "/data/passkey-auth.db"
|
||||||
|
|
||||||
|
cors:
|
||||||
|
allowedOrigins:
|
||||||
|
- "https://*.example.com"
|
||||||
|
|
||||||
|
auth:
|
||||||
|
requireApproval: true
|
||||||
|
cookieDomain: ".example.com"
|
||||||
|
allowedEmails:
|
||||||
|
- "admin@example.com"
|
||||||
|
# adminEmail will be set via environment variable
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
env:
|
||||||
|
- name: DEFAULT_EMAIL
|
||||||
|
value: "admin@example.com"
|
||||||
|
- name: CONFIG_PATH
|
||||||
|
value: "/app/config.yaml"
|
||||||
|
- name: ADMIN_EMAIL
|
||||||
|
value: "admin@example.com"
|
||||||
|
|
||||||
|
# Secret environment variables
|
||||||
|
secrets:
|
||||||
|
# Session secret for cookie signing
|
||||||
|
sessionSecret: "change-me-in-production-use-long-random-string"
|
||||||
|
|
||||||
|
# Additional environment variables from existing secrets
|
||||||
|
envFrom: []
|
||||||
|
# - secretRef:
|
||||||
|
# name: my-secret
|
||||||
|
|
||||||
|
# Additional volume mounts
|
||||||
|
volumeMounts: []
|
||||||
|
|
||||||
|
# Additional volumes
|
||||||
|
volumes: []
|
||||||
Executable
BIN
Binary file not shown.
Executable
+128
@@ -0,0 +1,128 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Helm Chart Validation Script
|
||||||
|
# This script validates the Helm chart before deployment
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CHART_DIR="helm/passkey-auth"
|
||||||
|
NAMESPACE="passkey-auth-test"
|
||||||
|
|
||||||
|
echo "🔍 Validating Passkey Auth Helm Chart..."
|
||||||
|
|
||||||
|
# Check if helm is installed
|
||||||
|
if ! command -v helm &> /dev/null; then
|
||||||
|
echo "❌ Helm is not installed. Please install Helm first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if kubectl is installed
|
||||||
|
if ! command -v kubectl &> /dev/null; then
|
||||||
|
echo "❌ kubectl is not installed. Please install kubectl first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Prerequisites check passed"
|
||||||
|
|
||||||
|
# Lint the chart
|
||||||
|
echo "🔧 Linting Helm chart..."
|
||||||
|
if helm lint $CHART_DIR; then
|
||||||
|
echo "✅ Chart linting passed"
|
||||||
|
else
|
||||||
|
echo "❌ Chart linting failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Template the chart with test values
|
||||||
|
echo "📝 Templating chart with test values..."
|
||||||
|
helm template test-release $CHART_DIR \
|
||||||
|
--set config.webauthn.rpId=test.example.com \
|
||||||
|
--set config.webauthn.rpOrigins="{https://test.example.com}" \
|
||||||
|
--set config.cors.allowedOrigins="{https://test.example.com}" \
|
||||||
|
--set config.auth.cookieDomain=".example.com" \
|
||||||
|
--set config.auth.allowedEmails="{admin@example.com}" \
|
||||||
|
--set secrets.sessionSecret="test-secret-for-validation-only" \
|
||||||
|
--set ingress.hosts[0].host=test.example.com \
|
||||||
|
--set ingress.tls[0].hosts="{test.example.com}" \
|
||||||
|
> /tmp/passkey-auth-template.yaml
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "✅ Chart templating passed"
|
||||||
|
else
|
||||||
|
echo "❌ Chart templating failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate Kubernetes manifests
|
||||||
|
echo "🔍 Validating Kubernetes manifests..."
|
||||||
|
if kubectl apply --dry-run=client -f /tmp/passkey-auth-template.yaml; then
|
||||||
|
echo "✅ Kubernetes manifest validation passed"
|
||||||
|
else
|
||||||
|
echo "❌ Kubernetes manifest validation failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for required values
|
||||||
|
echo "🔧 Checking for required configuration..."
|
||||||
|
|
||||||
|
REQUIRED_VALUES=(
|
||||||
|
"config.webauthn.rpId"
|
||||||
|
"config.webauthn.rpOrigins"
|
||||||
|
"secrets.sessionSecret"
|
||||||
|
)
|
||||||
|
|
||||||
|
for value in "${REQUIRED_VALUES[@]}"; do
|
||||||
|
if helm template test-release $CHART_DIR --show-only templates/configmap.yaml | grep -q "REQUIRED"; then
|
||||||
|
echo "❌ Required value not set: $value"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "✅ Required values check passed"
|
||||||
|
|
||||||
|
# Test with production values
|
||||||
|
if [ -f "$CHART_DIR/examples/values-production.yaml" ]; then
|
||||||
|
echo "🏭 Testing with production values..."
|
||||||
|
helm template test-release $CHART_DIR \
|
||||||
|
-f $CHART_DIR/examples/values-production.yaml \
|
||||||
|
--set secrets.sessionSecret="test-secret" \
|
||||||
|
> /tmp/passkey-auth-production.yaml
|
||||||
|
|
||||||
|
if kubectl apply --dry-run=client -f /tmp/passkey-auth-production.yaml; then
|
||||||
|
echo "✅ Production values validation passed"
|
||||||
|
else
|
||||||
|
echo "❌ Production values validation failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test with development values
|
||||||
|
if [ -f "$CHART_DIR/examples/values-development.yaml" ]; then
|
||||||
|
echo "🚀 Testing with development values..."
|
||||||
|
helm template test-release $CHART_DIR \
|
||||||
|
-f $CHART_DIR/examples/values-development.yaml \
|
||||||
|
> /tmp/passkey-auth-development.yaml
|
||||||
|
|
||||||
|
if kubectl apply --dry-run=client -f /tmp/passkey-auth-development.yaml; then
|
||||||
|
echo "✅ Development values validation passed"
|
||||||
|
else
|
||||||
|
echo "❌ Development values validation failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
rm -f /tmp/passkey-auth-*.yaml
|
||||||
|
|
||||||
|
echo "🎉 All validations passed! The Helm chart is ready for deployment."
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo "1. Update values in values.yaml or use --set flags"
|
||||||
|
echo "2. Install the chart: helm install my-passkey-auth $CHART_DIR"
|
||||||
|
echo "3. Configure your ingress controllers to use the auth backend"
|
||||||
|
echo ""
|
||||||
|
echo "For production deployment, make sure to:"
|
||||||
|
echo "• Set a secure session secret"
|
||||||
|
echo "• Configure proper domains and origins"
|
||||||
|
echo "• Set up TLS certificates"
|
||||||
|
echo "• Configure allowed email addresses"
|
||||||
Reference in New Issue
Block a user