Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8f98cd195 | ||
|
|
e40bac1b04 | ||
|
|
81cd97ba31 | ||
|
|
c8697f12d2 | ||
|
|
8f6ceec51d | ||
|
|
34d184fe89 | ||
|
|
48dcd71dc0 | ||
|
|
84ce8a80a4 | ||
|
|
f3b5b539ee | ||
|
|
23d3c193e8 | ||
|
|
06606c1bf9 | ||
|
|
03004d08c2 | ||
|
|
fd06e4cb74 | ||
|
|
458f595f7c | ||
|
|
70c6ea44ca | ||
|
|
eb43b574cb | ||
|
|
6052251d32 | ||
|
|
f99853f6f5 | ||
|
|
e17797f96b | ||
|
|
00b634d7c6 | ||
|
|
5634c425d1 | ||
|
|
4d5efafe2b | ||
|
|
f807bd740f | ||
|
|
50ae7d88df | ||
|
|
76a534cf9d | ||
|
|
df291aa89d | ||
|
|
ac8a04f76a | ||
|
|
d38f3fbfc1 | ||
|
|
f7b91a102a | ||
|
|
2bc283620c | ||
|
|
b6a400eed6 | ||
|
|
4fbe92d44a | ||
|
|
6f160ca8ee | ||
|
|
993ee45d23 | ||
|
|
052e8adec6 | ||
|
|
d97ea83fc6 | ||
|
|
df0985e8b1 | ||
|
|
c91e438287 | ||
|
|
328c8e8476 | ||
|
|
fcb5499d11 | ||
|
|
666d093cef | ||
|
|
8959c70a21 | ||
|
|
734fbaeffd | ||
|
|
155036b677 | ||
|
|
5f87e4b360 | ||
|
|
a0326f9749 |
29
.github/workflows/ci.yml
vendored
29
.github/workflows/ci.yml
vendored
@@ -17,33 +17,26 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node: [14.15.4]
|
||||
os: [macos-latest, windows-latest, ubuntu-18.04]
|
||||
node: [20.12.2]
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
include:
|
||||
- os: macos-latest
|
||||
friendlyName: macOS
|
||||
- os: windows-latest
|
||||
friendlyName: Windows
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
friendlyName: Linux
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Use Node.js ${{ matrix.node }}
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
|
||||
# This step can be removed as soon as official Windows arm64 builds are published:
|
||||
# https://github.com/nodejs/build/issues/2450#issuecomment-705853342
|
||||
- run: |
|
||||
$NodeVersion = (node --version) -replace '^.'
|
||||
$NodeFallbackVersion = "15.8.0"
|
||||
& .\script\download-node-lib-win-arm64.ps1 $NodeVersion $NodeFallbackVersion
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
name: Install Windows arm64 node.lib
|
||||
|
||||
- name: Install Python setup tools
|
||||
run: |
|
||||
python -m pip install --upgrade setuptools packaging
|
||||
- name: Install and build
|
||||
run: |
|
||||
yarn install
|
||||
@@ -57,12 +50,10 @@ jobs:
|
||||
run: npm run prebuild-napi-x64
|
||||
- name: Prebuild (arm64)
|
||||
run: npm run prebuild-napi-arm64
|
||||
if: ${{ matrix.os != 'ubuntu-18.04' }}
|
||||
if: ${{ matrix.os != 'ubuntu-latest' }}
|
||||
- name: Prebuild (Windows x86)
|
||||
run: npm run prebuild-napi-ia32
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
- name: Publish
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||
run: yarn upload
|
||||
env:
|
||||
GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: yarn prebuild --upload-all ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
70
.github/workflows/codeql-analysis.yml
vendored
70
.github/workflows/codeql-analysis.yml
vendored
@@ -1,70 +0,0 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '45 23 * * 1'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'cpp', 'javascript', 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
@@ -1 +1 @@
|
||||
12.14.1
|
||||
20.12.2
|
||||
|
||||
@@ -60,7 +60,7 @@ The equivalent Bash shell code looks like this:
|
||||
|
||||
```sh
|
||||
# environment variable
|
||||
GIT_ASKPASS="C:/some/path/to/desktop-trampoline.exe" \
|
||||
GIT_ASKPASS="C:/some/path/to/desktop-askpass-trampoline.exe" \
|
||||
# ensure Git doesn't block the process waiting for the user to provide input
|
||||
GIT_TERMINAL_PROMPT=0 \
|
||||
git \
|
||||
|
||||
81
binding.gyp
81
binding.gyp
@@ -1,15 +1,8 @@
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'desktop-trampoline',
|
||||
'target_defaults': {
|
||||
'defines': [
|
||||
"NAPI_VERSION=<(napi_build_version)",
|
||||
],
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'src/desktop-trampoline.c',
|
||||
'src/socket.c'
|
||||
],
|
||||
'include_dirs': [
|
||||
'<!(node -p "require(\'node-addon-api\').include_dir")',
|
||||
'include'
|
||||
@@ -42,9 +35,38 @@
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': { 'ExceptionHandling': 1 },
|
||||
},
|
||||
'conditions': [
|
||||
['OS=="win"', { 'defines': [ 'WINDOWS' ] }]
|
||||
]
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'desktop-askpass-trampoline',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'src/desktop-trampoline.c',
|
||||
'src/socket.c'
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
'link_settings': {
|
||||
'libraries': [ 'Ws2_32.lib' ]
|
||||
}
|
||||
}]
|
||||
]
|
||||
},
|
||||
{
|
||||
'target_name': 'desktop-credential-helper-trampoline',
|
||||
'type': 'executable',
|
||||
'defines': [
|
||||
'CREDENTIAL_HELPER'
|
||||
],
|
||||
'sources': [
|
||||
'src/desktop-trampoline.c',
|
||||
'src/socket.c'
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
'defines': [ 'WINDOWS' ],
|
||||
'link_settings': {
|
||||
'libraries': [ 'Ws2_32.lib' ]
|
||||
}
|
||||
@@ -53,51 +75,10 @@
|
||||
},
|
||||
{
|
||||
'target_name': 'ssh-wrapper',
|
||||
'defines': [
|
||||
"NAPI_VERSION=<(napi_build_version)",
|
||||
],
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'src/ssh-wrapper.c'
|
||||
],
|
||||
'include_dirs': [
|
||||
'<!(node -p "require(\'node-addon-api\').include_dir")',
|
||||
'include'
|
||||
],
|
||||
'xcode_settings': {
|
||||
'OTHER_CFLAGS': [
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
'-Werror=format-security',
|
||||
'-fPIC',
|
||||
'-D_FORTIFY_SOURCE=1',
|
||||
'-fstack-protector-strong'
|
||||
]
|
||||
},
|
||||
'cflags!': [
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
'-fPIC',
|
||||
'-pie',
|
||||
'-D_FORTIFY_SOURCE=1',
|
||||
'-fstack-protector-strong',
|
||||
'-Werror=format-security',
|
||||
'-fno-exceptions'
|
||||
],
|
||||
'cflags_cc!': [ '-fno-exceptions' ],
|
||||
'ldflags!': [
|
||||
'-z relro',
|
||||
'-z now'
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': { 'ExceptionHandling': 1 },
|
||||
},
|
||||
'conditions': [
|
||||
# For now only build it for macOS, since it's not needed on Windows
|
||||
['OS=="win"', {
|
||||
'defines': [ 'WINDOWS' ],
|
||||
}]
|
||||
]
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
7
index.d.ts
vendored
7
index.d.ts
vendored
@@ -1,5 +1,8 @@
|
||||
export function getDesktopTrampolinePath(): string
|
||||
export function getDesktopTrampolineFilename(): string
|
||||
export function getDesktopAskpassTrampolinePath(): string
|
||||
export function getDesktopAskpassTrampolineFilename(): string
|
||||
|
||||
export function getDesktopCredentialHelperTrampolinePath(): string
|
||||
export function getDesktopCredentialHelperTrampolineFilename(): string
|
||||
|
||||
export function getSSHWrapperPath(): string
|
||||
export function getSSHWrapperFilename(): string
|
||||
|
||||
31
index.js
31
index.js
@@ -1,18 +1,33 @@
|
||||
const Path = require('path')
|
||||
|
||||
function getDesktopTrampolinePath() {
|
||||
function getDesktopAskpassTrampolinePath() {
|
||||
return Path.join(
|
||||
__dirname,
|
||||
'build',
|
||||
'Release',
|
||||
getDesktopTrampolineFilename()
|
||||
getDesktopAskpassTrampolineFilename()
|
||||
)
|
||||
}
|
||||
|
||||
function getDesktopTrampolineFilename() {
|
||||
function getDesktopAskpassTrampolineFilename() {
|
||||
return process.platform === 'win32'
|
||||
? 'desktop-trampoline.exe'
|
||||
: 'desktop-trampoline'
|
||||
? 'desktop-askpass-trampoline.exe'
|
||||
: 'desktop-askpass-trampoline'
|
||||
}
|
||||
|
||||
function getDesktopCredentialHelperTrampolinePath() {
|
||||
return Path.join(
|
||||
__dirname,
|
||||
'build',
|
||||
'Release',
|
||||
getDesktopCredentialHelperTrampolineFilename()
|
||||
)
|
||||
}
|
||||
|
||||
function getDesktopCredentialHelperTrampolineFilename() {
|
||||
return process.platform === 'win32'
|
||||
? 'desktop-credential-helper-trampoline.exe'
|
||||
: 'desktop-credential-helper-trampoline'
|
||||
}
|
||||
|
||||
function getSSHWrapperPath() {
|
||||
@@ -24,8 +39,10 @@ function getSSHWrapperFilename() {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getDesktopTrampolinePath,
|
||||
getDesktopTrampolineFilename,
|
||||
getDesktopAskpassTrampolinePath,
|
||||
getDesktopAskpassTrampolineFilename,
|
||||
getDesktopCredentialHelperTrampolinePath,
|
||||
getDesktopCredentialHelperTrampolineFilename,
|
||||
getSSHWrapperPath,
|
||||
getSSHWrapperFilename,
|
||||
}
|
||||
|
||||
14
package.json
14
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "desktop-trampoline",
|
||||
"version": "0.9.8",
|
||||
"version": "0.9.11",
|
||||
"main": "index.js",
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
@@ -15,9 +15,9 @@
|
||||
"test": "jest",
|
||||
"lint": "prettier -c **/*.js **/*.md",
|
||||
"lint:fix": "prettier --write **/*.js **/*.md",
|
||||
"prebuild-napi-x64": "prebuild -t 3 -r napi -a x64 --strip --include-regex \"(desktop-trampoline|ssh-wrapper)(\\.exe)?$\"",
|
||||
"prebuild-napi-ia32": "prebuild -t 3 -r napi -a ia32 --strip --include-regex \"(desktop-trampoline|ssh-wrapper)(\\.exe)?$\"",
|
||||
"prebuild-napi-arm64": "prebuild -t 3 -r napi -a arm64 --strip --include-regex \"(desktop-trampoline|ssh-wrapper)(\\.exe)?$\"",
|
||||
"prebuild-napi-x64": "prebuild -t 3 -r napi -a x64 --strip --include-regex \"(desktop-(askpass|credential-helper)-trampoline|ssh-wrapper)(\\.exe)?$\"",
|
||||
"prebuild-napi-ia32": "prebuild -t 3 -r napi -a ia32 --strip --include-regex \"(desktop-(askpass|credential-helper)-trampoline|ssh-wrapper)(\\.exe)?$\"",
|
||||
"prebuild-napi-arm64": "prebuild -t 3 -r napi -a arm64 --strip --include-regex \"(desktop-(askpass|credential-helper)-trampoline|ssh-wrapper)(\\.exe)?$\"",
|
||||
"prebuild-all": "yarn prebuild-napi-x64 && yarn prebuild-napi-ia32 && yarn prebuild-napi-arm64",
|
||||
"upload": "node ./script/upload.js"
|
||||
},
|
||||
@@ -31,12 +31,12 @@
|
||||
"homepage": "https://github.com/desktop/desktop-trampoline#readme",
|
||||
"dependencies": {
|
||||
"node-addon-api": "^4.3.0",
|
||||
"prebuild-install": "^7.0.1"
|
||||
"prebuild-install": "^7.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jest": "^27.5.0",
|
||||
"node-gyp": "^8.4.1",
|
||||
"prebuild": "^11.0.3",
|
||||
"node-gyp": "^10.1.0",
|
||||
"prebuild": "^13.0.1",
|
||||
"prettier": "^2.5.1",
|
||||
"split2": "^4.1.0"
|
||||
},
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# This script can be removed as soon as official Windows arm64 builds are published:
|
||||
# https://github.com/nodejs/build/issues/2450#issuecomment-705853342
|
||||
|
||||
$nodeVersion = $args[0]
|
||||
$fallbackVersion = $args[1]
|
||||
|
||||
If ($null -eq $nodeVersion -Or $null -eq $fallbackVersion) {
|
||||
Write-Error "No NodeJS version given as argument to this file. Run it like download-nodejs-win-arm64.ps1 NODE_VERSION NODE_FALLBACK_VERSION"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$url = "https://unofficial-builds.nodejs.org/download/release/v$nodeVersion/win-arm64/node.lib"
|
||||
$fallbackUrl = "https://unofficial-builds.nodejs.org/download/release/v$fallbackVersion/win-arm64/node.lib"
|
||||
|
||||
# Always write to the $nodeVersion cache folder, even if we're using the fallbackVersion
|
||||
$cacheFolder = "$env:TEMP\prebuild\napi\$nodeVersion\arm64"
|
||||
|
||||
If (!(Test-Path $cacheFolder)) {
|
||||
New-Item -ItemType Directory -Force -Path $cacheFolder
|
||||
}
|
||||
|
||||
$output = "$cacheFolder\node.lib"
|
||||
$start_time = Get-Date
|
||||
|
||||
Try {
|
||||
Invoke-WebRequest -Uri $url -OutFile $output
|
||||
$downloadedNodeVersion = $nodeVersion
|
||||
} Catch {
|
||||
If ($_.Exception.Response -And $_.Exception.Response.StatusCode -eq "NotFound") {
|
||||
Write-Output "No arm64 node.lib found for Node Windows $nodeVersion, trying fallback version $fallbackVersion..."
|
||||
Invoke-WebRequest -Uri $fallbackUrl -OutFile $output
|
||||
$downloadedNodeVersion = $fallbackVersion
|
||||
}
|
||||
}
|
||||
|
||||
Write-Output "Downloaded arm64 NodeJS lib v$downloadedNodeVersion to $output in $((Get-Date).Subtract($start_time).Seconds) second(s)"
|
||||
@@ -1,14 +0,0 @@
|
||||
// to ensure that env not in the CI server log
|
||||
|
||||
const path = require('path')
|
||||
const { spawnSync } = require('child_process')
|
||||
|
||||
spawnSync(
|
||||
path.join(
|
||||
__dirname,
|
||||
'../node_modules/.bin/prebuild' +
|
||||
(process.platform === 'win32' ? '.cmd' : '')
|
||||
),
|
||||
['--upload-all', process.env.GITHUB_AUTH_TOKEN],
|
||||
{ stdio: 'inherit' }
|
||||
)
|
||||
@@ -9,6 +9,13 @@
|
||||
#define BUFFER_LENGTH 4096
|
||||
#define MAXIMUM_NUMBER_LENGTH 33
|
||||
|
||||
#ifdef CREDENTIAL_HELPER
|
||||
#define DESKTOP_TRAMPOLINE_IDENTIFIER "CREDENTIALHELPER"
|
||||
#else
|
||||
#define DESKTOP_TRAMPOLINE_IDENTIFIER "ASKPASS"
|
||||
#endif
|
||||
|
||||
|
||||
#define WRITE_STRING_OR_EXIT(dataName, dataString) \
|
||||
if (writeSocket(socket, dataString, strlen(dataString) + 1) != 0) { \
|
||||
printSocketError("ERROR: Couldn't send " dataName); \
|
||||
@@ -17,12 +24,9 @@ if (writeSocket(socket, dataString, strlen(dataString) + 1) != 0) { \
|
||||
|
||||
// This is a list of valid environment variables that GitHub Desktop might
|
||||
// send or expect to receive.
|
||||
#define NUMBER_OF_VALID_ENV_VARS 4
|
||||
#define NUMBER_OF_VALID_ENV_VARS 1
|
||||
static const char *sValidEnvVars[NUMBER_OF_VALID_ENV_VARS] = {
|
||||
"DESKTOP_TRAMPOLINE_IDENTIFIER",
|
||||
"DESKTOP_TRAMPOLINE_TOKEN",
|
||||
"DESKTOP_USERNAME",
|
||||
"DESKTOP_ENDPOINT",
|
||||
};
|
||||
|
||||
/** Returns 1 if a given env variable is valid, 0 otherwise. */
|
||||
@@ -83,8 +87,9 @@ int runTrampolineClient(SOCKET *outSocket, int argc, char **argv, char **envp) {
|
||||
}
|
||||
|
||||
// Get the number of environment variables
|
||||
char *validEnvVars[NUMBER_OF_VALID_ENV_VARS];
|
||||
int envc = 0;
|
||||
char *validEnvVars[NUMBER_OF_VALID_ENV_VARS + 1];
|
||||
validEnvVars[0] = "DESKTOP_TRAMPOLINE_IDENTIFIER=" DESKTOP_TRAMPOLINE_IDENTIFIER;
|
||||
int envc = 1;
|
||||
for (char **env = envp; *env != 0; env++) {
|
||||
if (isValidEnvVar(*env)) {
|
||||
validEnvVars[envc] = *env;
|
||||
@@ -102,7 +107,15 @@ int runTrampolineClient(SOCKET *outSocket, int argc, char **argv, char **envp) {
|
||||
WRITE_STRING_OR_EXIT("environment variable", validEnvVars[idx]);
|
||||
}
|
||||
|
||||
// TODO: send stdin stuff?
|
||||
char stdinBuffer[BUFFER_LENGTH + 1];
|
||||
int stdinBytes = 0;
|
||||
|
||||
#ifdef CREDENTIAL_HELPER
|
||||
stdinBytes = fread(stdinBuffer, sizeof(char), BUFFER_LENGTH, stdin);
|
||||
#endif
|
||||
|
||||
stdinBuffer[stdinBytes] = '\0';
|
||||
WRITE_STRING_OR_EXIT("stdin", stdinBuffer);
|
||||
|
||||
char buffer[BUFFER_LENGTH + 1];
|
||||
size_t totalBytesRead = 0;
|
||||
|
||||
@@ -2,65 +2,152 @@ const { stat, access } = require('fs').promises
|
||||
const { constants } = require('fs')
|
||||
const { execFile } = require('child_process')
|
||||
const { promisify } = require('util')
|
||||
const { getDesktopTrampolinePath } = require('../index')
|
||||
const {
|
||||
getDesktopAskpassTrampolinePath,
|
||||
getDesktopCredentialHelperTrampolinePath,
|
||||
} = require('../index')
|
||||
const split2 = require('split2')
|
||||
const { createServer } = require('net')
|
||||
|
||||
const trampolinePath = getDesktopTrampolinePath()
|
||||
const askPassTrampolinePath = getDesktopAskpassTrampolinePath()
|
||||
const helperTrampolinePath = getDesktopCredentialHelperTrampolinePath()
|
||||
const run = promisify(execFile)
|
||||
|
||||
describe('desktop-trampoline', () => {
|
||||
it('exists and is a regular file', async () =>
|
||||
expect((await stat(trampolinePath)).isFile()).toBe(true))
|
||||
expect((await stat(askPassTrampolinePath)).isFile()).toBe(true))
|
||||
|
||||
it('can be executed by current process', () =>
|
||||
access(trampolinePath, constants.X_OK))
|
||||
access(askPassTrampolinePath, constants.X_OK))
|
||||
|
||||
it('fails when required environment variables are missing', () =>
|
||||
expect(run(trampolinePath, ['Username'])).rejects.toThrow())
|
||||
expect(run(askPassTrampolinePath, ['Username'])).rejects.toThrow())
|
||||
|
||||
it('forwards arguments and valid environment variables correctly', async () => {
|
||||
const captureSession = () => {
|
||||
const output = []
|
||||
let resolveOutput = null
|
||||
|
||||
const outputPromise = new Promise(resolve => {
|
||||
resolveOutput = resolve
|
||||
})
|
||||
|
||||
const server = createServer(socket => {
|
||||
let timeoutId = null
|
||||
socket.pipe(split2(/\0/)).on('data', data => {
|
||||
output.push(data.toString('utf8'))
|
||||
})
|
||||
|
||||
// Don't send anything and just close the socket after the trampoline is
|
||||
// done forwarding data.
|
||||
socket.end()
|
||||
// Hack: consider the session finished after 100ms of inactivity.
|
||||
// In a real-world scenario, you'd have to parse the data to know when
|
||||
// the session is finished.
|
||||
if (timeoutId !== null) {
|
||||
clearTimeout(timeoutId)
|
||||
timeoutId = null
|
||||
}
|
||||
timeoutId = setTimeout(() => {
|
||||
resolveOutput(output)
|
||||
socket.end()
|
||||
server.close()
|
||||
}, 100)
|
||||
})
|
||||
})
|
||||
server.unref()
|
||||
|
||||
const startTrampolineServer = async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
server.on('error', e => reject(e))
|
||||
server.listen(0, '127.0.0.1', () => {
|
||||
resolve(server.address().port)
|
||||
})
|
||||
const serverPortPromise = new Promise((resolve, reject) => {
|
||||
server.on('error', e => reject(e))
|
||||
server.listen(0, '127.0.0.1', () => {
|
||||
resolve(server.address().port)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return [serverPortPromise, outputPromise]
|
||||
}
|
||||
|
||||
it('forwards arguments and valid environment variables correctly', async () => {
|
||||
const [portPromise, outputPromise] = captureSession()
|
||||
const port = await portPromise
|
||||
|
||||
const port = await startTrampolineServer()
|
||||
const env = {
|
||||
DESKTOP_TRAMPOLINE_IDENTIFIER: '123456',
|
||||
DESKTOP_TRAMPOLINE_TOKEN: '123456',
|
||||
DESKTOP_PORT: port,
|
||||
DESKTOP_USERNAME: 'sergiou87',
|
||||
DESKTOP_USERNAME_FAKE: 'fake-user',
|
||||
INVALID_VARIABLE: 'foo bar',
|
||||
}
|
||||
const opts = { env }
|
||||
|
||||
await run(trampolinePath, ['baz'], opts)
|
||||
await run(askPassTrampolinePath, ['baz'], opts)
|
||||
|
||||
const output = await outputPromise
|
||||
const outputArguments = output.slice(1, 2)
|
||||
expect(outputArguments).toStrictEqual(['baz'])
|
||||
// output[2] is the number of env variables
|
||||
const outputEnv = output.slice(3)
|
||||
const envc = parseInt(output[2])
|
||||
const outputEnv = output.slice(3, 3 + envc)
|
||||
expect(outputEnv).toHaveLength(2)
|
||||
expect(outputEnv).toContain('DESKTOP_TRAMPOLINE_IDENTIFIER=123456')
|
||||
expect(outputEnv).toContain(`DESKTOP_USERNAME=sergiou87`)
|
||||
expect(outputEnv).toContain('DESKTOP_TRAMPOLINE_TOKEN=123456')
|
||||
expect(outputEnv).toContain('DESKTOP_TRAMPOLINE_IDENTIFIER=ASKPASS')
|
||||
})
|
||||
|
||||
server.close()
|
||||
it('forwards stdin when running in credential-helper mode', async () => {
|
||||
const [portPromise, outputPromise] = captureSession()
|
||||
const port = await portPromise
|
||||
|
||||
const cp = run(helperTrampolinePath, ['get'], {
|
||||
env: { DESKTOP_PORT: port },
|
||||
})
|
||||
cp.child.stdin.end('oh hai\n')
|
||||
|
||||
await cp
|
||||
|
||||
const output = await outputPromise
|
||||
expect(output.at(-1)).toBe('oh hai\n')
|
||||
})
|
||||
|
||||
it("doesn't forward stdin when running in askpass mode", async () => {
|
||||
const [portPromise, outputPromise] = captureSession()
|
||||
const port = await portPromise
|
||||
|
||||
const cp = run(askPassTrampolinePath, ['get'], {
|
||||
env: { DESKTOP_PORT: port },
|
||||
})
|
||||
cp.child.stdin.end('oh hai\n')
|
||||
|
||||
await cp
|
||||
|
||||
const output = await outputPromise
|
||||
expect(output.at(-1)).toBe('')
|
||||
})
|
||||
|
||||
it('askpass handler ignores the DESKTOP_TRAMPOLINE_IDENTIFIER env var', async () => {
|
||||
const [portPromise, outputPromise] = captureSession()
|
||||
const port = await portPromise
|
||||
|
||||
const cp = run(askPassTrampolinePath, ['get'], {
|
||||
env: { DESKTOP_PORT: port, DESKTOP_TRAMPOLINE_IDENTIFIER: 'foo' },
|
||||
})
|
||||
cp.child.stdin.end('oh hai\n')
|
||||
|
||||
await cp
|
||||
|
||||
const output = await outputPromise
|
||||
const envc = parseInt(output[2])
|
||||
const outputEnv = output.slice(3, 3 + envc)
|
||||
expect(outputEnv).toContain('DESKTOP_TRAMPOLINE_IDENTIFIER=ASKPASS')
|
||||
})
|
||||
|
||||
it('credential handler ignores the DESKTOP_TRAMPOLINE_IDENTIFIER env var', async () => {
|
||||
const [portPromise, outputPromise] = captureSession()
|
||||
const port = await portPromise
|
||||
|
||||
const cp = run(helperTrampolinePath, ['get'], {
|
||||
env: { DESKTOP_PORT: port, DESKTOP_TRAMPOLINE_IDENTIFIER: 'foo' },
|
||||
})
|
||||
cp.child.stdin.end('oh hai\n')
|
||||
|
||||
await cp
|
||||
|
||||
const output = await outputPromise
|
||||
const envc = parseInt(output[2])
|
||||
const outputEnv = output.slice(3, 3 + envc)
|
||||
expect(outputEnv).toContain(
|
||||
'DESKTOP_TRAMPOLINE_IDENTIFIER=CREDENTIALHELPER'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user