fix: API_KEY is no longer required for login to work
This commit is contained in:
parent
a57e777a6b
commit
a63f4e4d52
9
CHANGELOG.md
Normal file
9
CHANGELOG.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
### 0.1.2 (May 1, 2024)
|
||||||
|
|
||||||
|
- Added support for renaming, expiring, removing, and managing the routes of a machine.
|
||||||
|
- Implemented an expiry check for machines which now reflect on the machine table.
|
||||||
|
- Fixed an issue where `HEADSCALE_CONTAINER` was needed to start even without the Docker integration.
|
||||||
|
- Removed the requirement for the root `API_KEY` unless OIDC was being used for authentication.
|
||||||
|
- Switched to [React Aria](https://react-spectrum.adobe.com/react-aria/) for better accessibility support.
|
||||||
|
- Cleaned up various different UI inconsistencies and copied components that could've been abstracted.
|
||||||
|
- Added a changelog for any new versions going forward.
|
||||||
@ -33,14 +33,6 @@ export async function loader() {
|
|||||||
throw new Error('The COOKIE_SECRET environment variable is required')
|
throw new Error('The COOKIE_SECRET environment variable is required')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!process.env.API_KEY) {
|
|
||||||
throw new Error('The API_KEY environment variable is required')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!process.env.HEADSCALE_CONTAINER) {
|
|
||||||
throw new Error('The HEADSCALE_CONTAINER environment variable is required')
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line unicorn/no-null
|
// eslint-disable-next-line unicorn/no-null
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@ -233,6 +233,7 @@ async function getOidcConfig() {
|
|||||||
let issuer = process.env.OIDC_ISSUER
|
let issuer = process.env.OIDC_ISSUER
|
||||||
let client = process.env.OIDC_CLIENT_ID
|
let client = process.env.OIDC_CLIENT_ID
|
||||||
let secret = process.env.OIDC_CLIENT_SECRET
|
let secret = process.env.OIDC_CLIENT_SECRET
|
||||||
|
const rootKey = process.env.API_KEY
|
||||||
|
|
||||||
if (!issuer || !client || !secret) {
|
if (!issuer || !client || !secret) {
|
||||||
const config = await getConfig()
|
const config = await getConfig()
|
||||||
@ -250,6 +251,10 @@ async function getOidcConfig() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!rootKey) {
|
||||||
|
throw new Error('Cannot use OIDC without the root API_KEY variable set')
|
||||||
|
}
|
||||||
|
|
||||||
return { issuer, client, secret }
|
return { issuer, client, secret }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
/* eslint-disable no-constant-condition */
|
/* eslint-disable no-constant-condition */
|
||||||
import { setTimeout } from 'node:timers/promises'
|
import { setTimeout } from 'node:timers/promises'
|
||||||
@ -6,7 +6,7 @@ import { setTimeout } from 'node:timers/promises'
|
|||||||
import { Client } from 'undici'
|
import { Client } from 'undici'
|
||||||
|
|
||||||
import { getContext } from './config'
|
import { getContext } from './config'
|
||||||
import { pull } from './headscale'
|
import { HeadscaleError, pull } from './headscale'
|
||||||
|
|
||||||
export async function sighupHeadscale() {
|
export async function sighupHeadscale() {
|
||||||
const context = await getContext()
|
const context = await getContext()
|
||||||
@ -61,9 +61,16 @@ export async function restartHeadscale() {
|
|||||||
let attempts = 0
|
let attempts = 0
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
await pull('v1/apikey', process.env.API_KEY!)
|
// Acceptable blank because API_KEY is not required
|
||||||
|
await pull('v1/apikey', process.env.API_KEY ?? '')
|
||||||
return
|
return
|
||||||
} catch {
|
} catch (error) {
|
||||||
|
// This means the server is up but the API key is invalid
|
||||||
|
// This can happen if the user only uses API_KEY via cookies
|
||||||
|
if (error instanceof HeadscaleError && error.status === 401) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
if (attempts > 10) {
|
if (attempts > 10) {
|
||||||
throw new Error('Headscale did not restart in time')
|
throw new Error('Headscale did not restart in time')
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export class HeadscaleError extends Error {
|
|||||||
|
|
||||||
export class FatalError extends Error {
|
export class FatalError extends Error {
|
||||||
constructor() {
|
constructor() {
|
||||||
super('The Headscale server is not accessible or the API_KEY is invalid.')
|
super('The Headscale server is not accessible or the supplied API key is invalid')
|
||||||
this.name = 'FatalError'
|
this.name = 'FatalError'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,9 +68,8 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- '3000:3000'
|
- '3000:3000'
|
||||||
environment:
|
environment:
|
||||||
# These are always required for Headplane to work
|
# This is always required for Headplane to work
|
||||||
COOKIE_SECRET: 'abcdefghijklmnopqrstuvwxyz'
|
COOKIE_SECRET: 'abcdefghijklmnopqrstuvwxyz'
|
||||||
API_KEY: 'abcdefghijklmnopqrstuvwxyz'
|
|
||||||
|
|
||||||
HEADSCALE_CONTAINER: 'headscale'
|
HEADSCALE_CONTAINER: 'headscale'
|
||||||
DISABLE_API_KEY_LOGIN: 'true'
|
DISABLE_API_KEY_LOGIN: 'true'
|
||||||
@ -82,6 +81,11 @@ services:
|
|||||||
OIDC_CLIENT_ID: 'headscale'
|
OIDC_CLIENT_ID: 'headscale'
|
||||||
OIDC_ISSUER: 'https://sso.example.com'
|
OIDC_ISSUER: 'https://sso.example.com'
|
||||||
OIDC_CLIENT_SECRET: 'super_secret_client_secret'
|
OIDC_CLIENT_SECRET: 'super_secret_client_secret'
|
||||||
|
|
||||||
|
# This NEEDS to be set with OIDC, regardless of what's in the config
|
||||||
|
# This needs to be a very long-lived (999 day) API key used to create
|
||||||
|
# shorter ones for OIDC and allow the OIDC functionality to work
|
||||||
|
API_KEY: 'abcdefghijklmnopqrstuvwxyz'
|
||||||
```
|
```
|
||||||
|
|
||||||
> For a breakdown of each configuration variable, please refer to the [Configuration](/docs/Configuration.md) guide.
|
> For a breakdown of each configuration variable, please refer to the [Configuration](/docs/Configuration.md) guide.
|
||||||
|
|||||||
@ -28,13 +28,17 @@ services:
|
|||||||
- '3000:3000'
|
- '3000:3000'
|
||||||
environment:
|
environment:
|
||||||
HEADSCALE_URL: 'http://headscale:8080'
|
HEADSCALE_URL: 'http://headscale:8080'
|
||||||
API_KEY: 'abcdefghijklmnopqrstuvwxyz'
|
|
||||||
COOKIE_SECRET: 'abcdefghijklmnopqrstuvwxyz'
|
COOKIE_SECRET: 'abcdefghijklmnopqrstuvwxyz'
|
||||||
|
|
||||||
|
# These are all optional!
|
||||||
HEADSCALE_CONTAINER: 'headscale'
|
HEADSCALE_CONTAINER: 'headscale'
|
||||||
|
API_KEY: 'abcdefghijklmnopqrstuvwxyz'
|
||||||
OIDC_CLIENT_ID: 'headscale'
|
OIDC_CLIENT_ID: 'headscale'
|
||||||
OIDC_ISSUER: 'https://sso.example.com'
|
OIDC_ISSUER: 'https://sso.example.com'
|
||||||
OIDC_CLIENT_SECRET: 'super_secret_client_secret'
|
OIDC_CLIENT_SECRET: 'super_secret_client_secret'
|
||||||
DISABLE_API_KEY_LOGIN: 'true'
|
DISABLE_API_KEY_LOGIN: 'true'
|
||||||
|
|
||||||
|
# These are the default values
|
||||||
HOST: '0.0.0.0'
|
HOST: '0.0.0.0'
|
||||||
PORT: '3000'
|
PORT: '3000'
|
||||||
```
|
```
|
||||||
|
|||||||
@ -4,9 +4,8 @@ You can configure Headplane using environment variables.
|
|||||||
|
|
||||||
#### Required Variables
|
#### Required Variables
|
||||||
|
|
||||||
- **`HEADSCALE_URL`**: The public URL of your Headscale server.
|
|
||||||
- **`API_KEY`**: An API key used to issue new ones for sessions (keep expiry fairly long).
|
|
||||||
- **`COOKIE_SECRET`**: A secret used to sign cookies (use a relatively long and random string).
|
- **`COOKIE_SECRET`**: A secret used to sign cookies (use a relatively long and random string).
|
||||||
|
- **`HEADSCALE_URL`**: The public URL of your Headscale server (not required if using the configuration file).
|
||||||
|
|
||||||
#### Optional Variables
|
#### Optional Variables
|
||||||
|
|
||||||
@ -24,6 +23,7 @@ If you use the Headscale configuration integration, these are not required.
|
|||||||
- **`OIDC_ISSUER`**: The issuer URL of your OIDC provider.
|
- **`OIDC_ISSUER`**: The issuer URL of your OIDC provider.
|
||||||
- **`OIDC_CLIENT_ID`**: The client ID of your OIDC provider.
|
- **`OIDC_CLIENT_ID`**: The client ID of your OIDC provider.
|
||||||
- **`OIDC_CLIENT_SECRET`**: The client secret of your OIDC provider.
|
- **`OIDC_CLIENT_SECRET`**: The client secret of your OIDC provider.
|
||||||
|
- **`API_KEY`**: An API key used to issue new ones for sessions (keep expiry fairly long).
|
||||||
- **`DISABLE_API_KEY_LOGIN`**: If you want to disable API key login, set this to `true`.
|
- **`DISABLE_API_KEY_LOGIN`**: If you want to disable API key login, set this to `true`.
|
||||||
|
|
||||||
Here's what an example with Authelia would look like if you used the same client for both Headscale and Headplane.
|
Here's what an example with Authelia would look like if you used the same client for both Headscale and Headplane.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user