В VSCode существует несколько способов хранить настройки пользователя. До прихода версии 1.53.0 конфиденциальную информацию приходилось сохранять в Memento объектах в workspaceState и globalState или например keytar. А хранение паролей с токенами в стандартном конфигурационном файле или с помощью переменных окружения, являлось не самой лучшей идеей, так как эти данные могли быть прочитаны и кэшированы другими расширениями.
В статье мы посмотрим на способы чтения данных из settings.json
и environment variables
. А затем создадим класс с минимальным функционалом, отвечающий за хранение и отдачу ключей со значениями из VSCode SecretStorage.
Проект мы условно назовем fancycolor
. Процесс инициализации проекта подробно расписан в документации VSCode Extensions, поэтому сразу приступим к интересному.
settings.json
Все настройки от всех VSCode extensions хранятся в общем файле settings.json
и соответственно могут быть доступны из любого расширения. К примеру, из нашего приложения fancycolor
мы можем легко прочитать список всех хостов и соответствующие им платформы из нашего конфига другого популярного приложения SSH - Remote
.
const configurationWorkspace = workspace.getConfiguration()
const sshRemotePlatform: string | undefined = configurationWorkspace.get(
"remote.SSH.remotePlatform"
)
console.log(sshRemotePlatform)
Данный код выведет список вашей конфигурации для расширения SSH - Remote
.
Proxy {ubuntu: 'linux', home: 'linux', raspberry: 'linux'}
environment variables
VSCode расширения по умолчанию имеют доступ к переменным окружения пользователя. Все переменные которые вы сохранили в .bashrc
в Linux или User.Environment
в Windows можно получить с помощью глобального объекта process.env
.
Например создадим файл /home/ubuntu/.env
с переменной ACCESS_TOKEN_ENV
и добавим его в .bashrc
.
echo 'export ACCESS_TOKEN_ENV="d8aba3b2-fda0-414a-b867-4798b7892bb4"' >> /home/ubuntu/.env
echo "source /home/ubuntu/.env" >> /home/ubuntu/.bashrc
В Windows тоже самое достигается через Powershell.
[System.Environment]::SetEnvironmentVariable('ACCESS_TOKEN_ENV', 'd8aba3b2-fda0-414a-b867-4798b7892bb4', [System.EnvironmentVariableTarget]::User)
Теперь прочитаем его в VSCode fancycolor
extension.
import * as process from "process"
export const accessTokenEnv = process.env["ACCESS_TOKEN_ENV"]
console.log(accessTokenEnv)
В выводе мы видим наш токен.
d8aba3b2-fda0-414a-b867-4798b7892bb4
SecretStorage
На сегодняшний день является лучшим способом хранения паролей, логинов, токенов и другой конфиденциальной информации в VSCode. Для демонстрации создадим простенький класс AuthSettings
, где будем хранить fancycolor_token
, с минимально необходимыми методами:
init
для инициализации нашего SecretStoragegetter
instance
storeAuthData
для записи в SecretStoragegetAuthData
для извлечения данных из SecretStorage
import { ExtensionContext, SecretStorage } from "vscode"
export default class AuthSettings {
private static _instance: AuthSettings
constructor(private secretStorage: SecretStorage) {}
static init(context: ExtensionContext): void {
/*
Create instance of new AuthSettings.
*/
AuthSettings._instance = new AuthSettings(context.secrets)
}
static get instance(): AuthSettings {
/*
Getter of our AuthSettings existing instance.
*/
return AuthSettings._instance
}
async storeAuthData(token?: string): Promise<void> {
/*
Update values in bugout_auth secret storage.
*/
if (token) {
this.secretStorage.store("fancycolor_token", token)
}
}
async getAuthData(): Promise<string | undefined> {
/*
Retrieve data from secret storage.
*/
return await this.secretStorage.get("fancycolor_token")
}
}
В extension.ts
напишем функционал позволяющий добавлять и извлекать токен с помощью команд в Command Palette.
import * as vscode from "vscode"
import AuthSettings from "./settings"
export function activate(context: vscode.ExtensionContext) {
// Initialize and get current instance of our Secret Storage
AuthSettings.init(context)
const settings = AuthSettings.instance
// Register commands to save and retrieve token
vscode.commands.registerCommand("fancycolor.setToken", async () => {
const tokenInput = await vscode.window.showInputBox()
await settings.storeAuthData(tokenInput)
})
vscode.commands.registerCommand("fancycolor.getToken", async () => {
const tokenOutput = await settings.getAuthData()
console.log(tokenOutput)
})
}
export function deactivate() {}
Останется только в package.json
зарегистрировать команды fancycolor.setToken
и fancycolor.getToken
. В последствии при работе с VSCode SecretStorage, мы сможем обратиться исключительно к конкретному SecretStorage созданному для нашего приложения, которому будет присвоен свой _id: 'undefined_publisher.fancycolor'
.