Improve password handling
- Error out if auth is enabled but no password is passed in - Indicate password location on login page
This commit is contained in:
parent
524b0205e9
commit
c0d6eb4664
@ -22,6 +22,7 @@ rules:
|
|||||||
# For overloads.
|
# For overloads.
|
||||||
no-dupe-class-members: off
|
no-dupe-class-members: off
|
||||||
"@typescript-eslint/no-use-before-define": off
|
"@typescript-eslint/no-use-before-define": off
|
||||||
|
"@typescript-eslint/no-non-null-assertion": off
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
# Does not work with CommonJS unfortunately.
|
# Does not work with CommonJS unfortunately.
|
||||||
|
@ -56,8 +56,7 @@
|
|||||||
"stylelint": "^13.0.0",
|
"stylelint": "^13.0.0",
|
||||||
"stylelint-config-recommended": "^3.0.0",
|
"stylelint-config-recommended": "^3.0.0",
|
||||||
"ts-node": "^8.4.1",
|
"ts-node": "^8.4.1",
|
||||||
"typescript": "3.7.2",
|
"typescript": "3.7.2"
|
||||||
"yarn": "^1.22.4"
|
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@types/node": "^12.12.7",
|
"@types/node": "^12.12.7",
|
||||||
@ -79,7 +78,8 @@
|
|||||||
"tar": "^6.0.1",
|
"tar": "^6.0.1",
|
||||||
"tar-fs": "^2.0.0",
|
"tar-fs": "^2.0.0",
|
||||||
"ws": "^7.2.0",
|
"ws": "^7.2.0",
|
||||||
"xdg-basedir": "^4.0.0"
|
"xdg-basedir": "^4.0.0",
|
||||||
|
"yarn": "^1.22.4"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"code-server": "out/node/entry.js"
|
"code-server": "out/node/entry.js"
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<div class="card-box">
|
<div class="card-box">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h1 class="main">Welcome to code-server</h1>
|
<h1 class="main">Welcome to code-server</h1>
|
||||||
<div class="sub">Please log in below. Check code-server's logs for the generated password.</div>
|
<div class="sub">Please log in below. {{PASSWORD_MSG}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<form class="login-form" method="post">
|
<form class="login-form" method="post">
|
||||||
|
@ -2,8 +2,8 @@ import * as http from "http"
|
|||||||
import * as limiter from "limiter"
|
import * as limiter from "limiter"
|
||||||
import * as querystring from "querystring"
|
import * as querystring from "querystring"
|
||||||
import { HttpCode, HttpError } from "../../common/http"
|
import { HttpCode, HttpError } from "../../common/http"
|
||||||
import { AuthType, HttpProvider, HttpResponse, Route } from "../http"
|
import { AuthType, HttpProvider, HttpProviderOptions, HttpResponse, Route } from "../http"
|
||||||
import { hash } from "../util"
|
import { hash, humanPath } from "../util"
|
||||||
|
|
||||||
interface LoginPayload {
|
interface LoginPayload {
|
||||||
password?: string
|
password?: string
|
||||||
@ -18,6 +18,14 @@ interface LoginPayload {
|
|||||||
* Login HTTP provider.
|
* Login HTTP provider.
|
||||||
*/
|
*/
|
||||||
export class LoginHttpProvider extends HttpProvider {
|
export class LoginHttpProvider extends HttpProvider {
|
||||||
|
public constructor(
|
||||||
|
options: HttpProviderOptions,
|
||||||
|
private readonly configFile: string,
|
||||||
|
private readonly envPassword: boolean,
|
||||||
|
) {
|
||||||
|
super(options)
|
||||||
|
}
|
||||||
|
|
||||||
public async handleRequest(route: Route, request: http.IncomingMessage): Promise<HttpResponse> {
|
public async handleRequest(route: Route, request: http.IncomingMessage): Promise<HttpResponse> {
|
||||||
if (this.options.auth !== AuthType.Password || !this.isRoot(route)) {
|
if (this.options.auth !== AuthType.Password || !this.isRoot(route)) {
|
||||||
throw new HttpError("Not found", HttpCode.NotFound)
|
throw new HttpError("Not found", HttpCode.NotFound)
|
||||||
@ -46,6 +54,11 @@ export class LoginHttpProvider extends HttpProvider {
|
|||||||
public async getRoot(route: Route, error?: Error): Promise<HttpResponse> {
|
public async getRoot(route: Route, error?: Error): Promise<HttpResponse> {
|
||||||
const response = await this.getUtf8Resource(this.rootPath, "src/browser/pages/login.html")
|
const response = await this.getUtf8Resource(this.rootPath, "src/browser/pages/login.html")
|
||||||
response.content = response.content.replace(/{{ERROR}}/, error ? `<div class="error">${error.message}</div>` : "")
|
response.content = response.content.replace(/{{ERROR}}/, error ? `<div class="error">${error.message}</div>` : "")
|
||||||
|
let passwordMsg = `Check the config file at ${humanPath(this.configFile)} for the password.`
|
||||||
|
if (this.envPassword) {
|
||||||
|
passwordMsg = "Password was set from $PASSWORD."
|
||||||
|
}
|
||||||
|
response.content = response.content.replace(/{{PASSWORD_MSG}}/g, passwordMsg)
|
||||||
return this.replaceTemplates(route, response)
|
return this.replaceTemplates(route, response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,10 +36,21 @@ const main = async (cliArgs: Args): Promise<void> => {
|
|||||||
// This prioritizes the flags set in args over the ones in the config file.
|
// This prioritizes the flags set in args over the ones in the config file.
|
||||||
let args = Object.assign(configArgs, cliArgs)
|
let args = Object.assign(configArgs, cliArgs)
|
||||||
|
|
||||||
|
if (!args.auth) {
|
||||||
|
args = {
|
||||||
|
...args,
|
||||||
|
auth: AuthType.Password,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logger.trace(`Using extensions-dir at ${humanPath(args["extensions-dir"])}`)
|
logger.trace(`Using extensions-dir at ${humanPath(args["extensions-dir"])}`)
|
||||||
logger.trace(`Using user-data-dir at ${humanPath(args["user-data-dir"])}`)
|
logger.trace(`Using user-data-dir at ${humanPath(args["user-data-dir"])}`)
|
||||||
|
|
||||||
|
const envPassword = !!process.env.PASSWORD
|
||||||
const password = args.auth === AuthType.Password && (process.env.PASSWORD || args.password)
|
const password = args.auth === AuthType.Password && (process.env.PASSWORD || args.password)
|
||||||
|
if (args.auth === AuthType.Password && !password) {
|
||||||
|
throw new Error("Please pass in a password via the config file or $PASSWORD")
|
||||||
|
}
|
||||||
const [host, port] = bindAddrFromAllSources(cliArgs, configArgs)
|
const [host, port] = bindAddrFromAllSources(cliArgs, configArgs)
|
||||||
|
|
||||||
// Spawn the main HTTP server.
|
// Spawn the main HTTP server.
|
||||||
@ -69,7 +80,7 @@ const main = async (cliArgs: Args): Promise<void> => {
|
|||||||
const api = httpServer.registerHttpProvider("/api", ApiHttpProvider, httpServer, vscode, args["user-data-dir"])
|
const api = httpServer.registerHttpProvider("/api", ApiHttpProvider, httpServer, vscode, args["user-data-dir"])
|
||||||
const update = httpServer.registerHttpProvider("/update", UpdateHttpProvider, false)
|
const update = httpServer.registerHttpProvider("/update", UpdateHttpProvider, false)
|
||||||
httpServer.registerHttpProvider("/proxy", ProxyHttpProvider)
|
httpServer.registerHttpProvider("/proxy", ProxyHttpProvider)
|
||||||
httpServer.registerHttpProvider("/login", LoginHttpProvider)
|
httpServer.registerHttpProvider("/login", LoginHttpProvider, args.config!, envPassword)
|
||||||
httpServer.registerHttpProvider("/static", StaticHttpProvider)
|
httpServer.registerHttpProvider("/static", StaticHttpProvider)
|
||||||
httpServer.registerHttpProvider("/dashboard", DashboardHttpProvider, api, update)
|
httpServer.registerHttpProvider("/dashboard", DashboardHttpProvider, api, update)
|
||||||
|
|
||||||
@ -79,15 +90,8 @@ const main = async (cliArgs: Args): Promise<void> => {
|
|||||||
const serverAddress = await httpServer.listen()
|
const serverAddress = await httpServer.listen()
|
||||||
logger.info(`HTTP server listening on ${serverAddress}`)
|
logger.info(`HTTP server listening on ${serverAddress}`)
|
||||||
|
|
||||||
if (!args.auth) {
|
|
||||||
args = {
|
|
||||||
...args,
|
|
||||||
auth: AuthType.Password,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.auth === AuthType.Password) {
|
if (args.auth === AuthType.Password) {
|
||||||
if (process.env.PASSWORD) {
|
if (envPassword) {
|
||||||
logger.info(" - Using password from $PASSWORD")
|
logger.info(" - Using password from $PASSWORD")
|
||||||
} else {
|
} else {
|
||||||
logger.info(` - Using password from ${humanPath(args.config)}`)
|
logger.info(` - Using password from ${humanPath(args.config)}`)
|
||||||
|
Reference in New Issue
Block a user