Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions packages/core/src/awsService/ec2/sshKeyPair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
import { fs } from '../../shared'
import { chmodSync } from 'fs'
import { ToolkitError } from '../../shared/errors'
import { ChildProcess } from '../../shared/utilities/childProcess'
import { Timeout } from '../../shared/utilities/timeoutUtils'
Expand Down Expand Up @@ -40,7 +39,7 @@ export class SshKeyPair {
if (result.exitCode !== 0) {
throw new ToolkitError('ec2: Failed to generate ssh key', { details: { stdout: result.stdout } })
}
chmodSync(keyPath, 0o600)
await fs.chmod(keyPath, 0o600)
}

public getPublicKeyPath(): string {
Expand Down
15 changes: 15 additions & 0 deletions packages/core/src/shared/fs/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import vscode from 'vscode'
import os from 'os'
import { promises as nodefs, constants as nodeConstants, WriteFileOptions } from 'fs'
import { chmod } from 'fs/promises'
import { isCloud9 } from '../extensionUtilities'
import _path from 'path'
import {
Expand Down Expand Up @@ -356,6 +357,20 @@ export class FileSystem {
return await vfs.stat(path)
}

/**
* Change permissions on file. Note that this will do nothing on browser.
* @param uri file whose permissions should be set.
* @param mode new permissions in octal notation.
* More info: https://nodejs.org/api/fs.html#fspromiseschmodpath-mode
* Examples: https://www.geeksforgeeks.org/node-js-fspromises-chmod-method/
*/
async chmod(uri: vscode.Uri | string, mode: number): Promise<void> {
if (!this.isWeb) {
const path = this.#toUri(uri)
await chmod(path.fsPath, mode)
}
}

/**
* Deletes a file or directory. It is not an error if the file/directory does not exist, unless
* its parent directory is not listable (executable).
Expand Down
11 changes: 10 additions & 1 deletion packages/core/src/test/awsService/ec2/sshKeyPair.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import * as vscode from 'vscode'
import assert from 'assert'
import * as sinon from 'sinon'
import * as path from 'path'
import * as os from 'os'
import { stat } from 'fs/promises'
import { SshKeyPair } from '../../../awsService/ec2/sshKeyPair'
import { createTestWorkspaceFolder, installFakeClock } from '../../testUtil'
import { InstalledClock } from '@sinonjs/fake-timers'
import { ChildProcess } from '../../../shared/utilities/childProcess'
import { fs } from '../../../shared'
import { fs, globals } from '../../../shared'

describe('SshKeyUtility', async function () {
let temporaryDirectory: string
Expand Down Expand Up @@ -57,6 +59,13 @@ describe('SshKeyUtility', async function () {
// Check private key header for algorithm name
assert.strictEqual(result.stdout.includes('[ED25519 256]'), true)
})

it('sets permission of the file to read/write owner', async function () {
if (!globals.isWeb && os.platform() !== 'win32') {
const result = await stat(keyPair.getPrivateKeyPath())
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh I guess we will need fs.stat(), later...

assert.strictEqual(result.mode & 0o777, 0o600)
}
})
})

it('properly names the public key', function () {
Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/test/shared/fs/fs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import vscode from 'vscode'
import * as path from 'path'
import * as utils from 'util'
import { existsSync, mkdirSync, promises as nodefs, readFileSync, rmSync } from 'fs'
import { stat } from 'fs/promises'
import nodeFs from 'fs'
import { FakeExtensionContext } from '../../fakeExtensionContext'
import fs, { FileSystem } from '../../../shared/fs/fs'
Expand Down Expand Up @@ -380,6 +381,23 @@ describe('FileSystem', function () {
})
})

describe('chmod()', async function () {
it('changes permissions when not on web, otherwise does not throw', async function () {
const filePath = await makeFile('test.txt', 'hello world', { mode: 0o777 })
await fs.chmod(filePath, 0o644)
// chmod doesn't exist on windows, non-unix permission system.
if (!globals.isWeb && os.platform() !== 'win32') {
const result = await stat(filePath)
assert.strictEqual(result.mode & 0o777, 0o644)
}
})

it('throws if no file exists', async function () {
const filePath = createTestPath('thisDoesNotExist.txt')
await assert.rejects(() => fs.chmod(filePath, 0o644))
})
})

describe('rename()', async () => {
it('renames a file', async () => {
const oldPath = await makeFile('oldFile.txt', 'hello world')
Expand Down