@ydbjs/auth
Version:
Authentication providers for YDB: static credentials, tokens, anonymous, and cloud metadata. Integrates with the core driver for secure access.
152 lines • 7 kB
JavaScript
import * as fs from 'node:fs';
import * as tls from 'node:tls';
import { loggers } from '@ydbjs/debug';
import { AccessTokenCredentialsProvider } from './access-token.js';
import { AnonymousCredentialsProvider } from './anonymous.js';
import { CredentialsProvider } from './index.js';
import { MetadataCredentialsProvider } from './metadata.js';
import { StaticCredentialsProvider } from './static.js';
let debug = loggers.auth.extend('environ');
/**
* Reads TLS/SSL configuration from environment variables.
*
* Supported variables:
* - CA: `YDB_SSL_ROOT_CERTIFICATES_FILE` (file path) or `NODE_EXTRA_CA_CERTS` (file path)
* or `YDB_SSL_ROOT_CERTIFICATES` (PEM string)
* - Client cert: `YDB_SSL_CERTIFICATE_FILE` (file path) or `YDB_SSL_CERTIFICATE` (PEM string)
* - Client key: `YDB_SSL_PRIVATE_KEY_FILE` (file path) or `YDB_SSL_PRIVATE_KEY` (PEM string)
*
* File variants take priority over string variants.
*
* @returns `tls.SecureContextOptions` if any TLS env vars are set, `undefined` otherwise.
*/
export function getSecureOptionsFromEnviron() {
let caFile = process.env.YDB_SSL_ROOT_CERTIFICATES_FILE ?? process.env.NODE_EXTRA_CA_CERTS;
let crtFile = process.env.YDB_SSL_CERTIFICATE_FILE;
let keyFile = process.env.YDB_SSL_PRIVATE_KEY_FILE;
let caString = process.env.YDB_SSL_ROOT_CERTIFICATES;
let crtString = process.env.YDB_SSL_CERTIFICATE;
let keyString = process.env.YDB_SSL_PRIVATE_KEY;
if (!caFile && !crtFile && !keyFile && !caString && !crtString && !keyString) {
return undefined;
}
if (caFile && caString) {
throw new Error('Ambiguous CA configuration: both YDB_SSL_ROOT_CERTIFICATES_FILE (or NODE_EXTRA_CA_CERTS) and YDB_SSL_ROOT_CERTIFICATES are set. Use only one.');
}
if (crtFile && crtString) {
throw new Error('Ambiguous client certificate configuration: both YDB_SSL_CERTIFICATE_FILE and YDB_SSL_CERTIFICATE are set. Use only one.');
}
if (keyFile && keyString) {
throw new Error('Ambiguous private key configuration: both YDB_SSL_PRIVATE_KEY_FILE and YDB_SSL_PRIVATE_KEY are set. Use only one.');
}
let options = {};
if (caFile) {
debug.log('reading CA certificate from %s', caFile);
options.ca = fs.readFileSync(caFile);
}
else if (caString) {
debug.log('using CA certificate from env string');
options.ca = caString;
}
if (crtFile) {
debug.log('reading client certificate from %s', crtFile);
options.cert = fs.readFileSync(crtFile);
}
else if (crtString) {
debug.log('using client certificate from env string');
options.cert = crtString;
}
if (keyFile) {
debug.log('reading client private key from %s', keyFile);
options.key = fs.readFileSync(keyFile);
}
else if (keyString) {
debug.log('using client private key from env string');
options.key = keyString;
}
return options;
}
/**
* A credentials provider that auto-detects the authentication method
* from environment variables, following the official YDB SDK conventions.
*
* Detection priority (first match wins):
* 1. `YDB_ANONYMOUS_CREDENTIALS=1` → Anonymous
* 2. `YDB_METADATA_CREDENTIALS=1` → Metadata
* - `YDB_METADATA_CREDENTIALS_ENDPOINT` — custom metadata endpoint
* - `YDB_METADATA_CREDENTIALS_FLAVOR` — custom metadata flavor (e.g. `Google`)
* 3. `YDB_ACCESS_TOKEN_CREDENTIALS` → Access Token
* 4. `YDB_STATIC_CREDENTIALS_USER` → Static (username/password)
* 5. None → Anonymous
*
* TLS/SSL is auto-detected from environment variables and exposed via `secureOptions`:
* - `YDB_SSL_ROOT_CERTIFICATES_FILE` / `NODE_EXTRA_CA_CERTS` (file) or `YDB_SSL_ROOT_CERTIFICATES` (PEM string)
* - `YDB_SSL_CERTIFICATE_FILE` (file) or `YDB_SSL_CERTIFICATE` (PEM string)
* - `YDB_SSL_PRIVATE_KEY_FILE` (file) or `YDB_SSL_PRIVATE_KEY` (PEM string)
*
* @example
* ```ts
* import { EnvironCredentialsProvider } from '@ydbjs/auth/environ'
*
* let creds = new EnvironCredentialsProvider(connectionString)
* let driver = new Driver(connectionString, {
* credentialsProvider: creds,
* secureOptions: creds.secureOptions,
* })
* ```
*/
export class EnvironCredentialsProvider extends CredentialsProvider {
#inner;
/**
* TLS/SSL options detected from environment variables.
* Pass this to `Driver` as `secureOptions`.
*/
secureOptions;
constructor(connectionString) {
super();
this.secureOptions = getSecureOptionsFromEnviron();
this.#inner = this.#detect(connectionString);
debug.log('detected credentials provider: %s, secureOptions: %s', this.#inner.constructor.name, this.secureOptions ? 'yes' : 'no');
}
async getToken(force, signal) {
return this.#inner.getToken(force, signal);
}
#detect(connectionString) {
if (process.env.YDB_ANONYMOUS_CREDENTIALS === '1') {
debug.log('YDB_ANONYMOUS_CREDENTIALS=1, using anonymous auth');
return new AnonymousCredentialsProvider();
}
if (process.env.YDB_METADATA_CREDENTIALS === '1') {
let endpoint = process.env.YDB_METADATA_CREDENTIALS_ENDPOINT;
let flavor = process.env.YDB_METADATA_CREDENTIALS_FLAVOR;
debug.log('YDB_METADATA_CREDENTIALS=1, using metadata auth (endpoint: %s, flavor: %s)', endpoint ?? 'default', flavor ?? 'default');
return new MetadataCredentialsProvider({
...(endpoint && { endpoint }),
...(flavor && { flavor }),
});
}
if (process.env.YDB_ACCESS_TOKEN_CREDENTIALS) {
debug.log('YDB_ACCESS_TOKEN_CREDENTIALS is set, using access token auth');
return new AccessTokenCredentialsProvider({
token: process.env.YDB_ACCESS_TOKEN_CREDENTIALS,
});
}
if (process.env.YDB_STATIC_CREDENTIALS_USER) {
let username = process.env.YDB_STATIC_CREDENTIALS_USER;
let password = process.env.YDB_STATIC_CREDENTIALS_PASSWORD ?? '';
let endpoint = process.env.YDB_STATIC_CREDENTIALS_ENDPOINT;
if (!endpoint) {
if (!connectionString) {
throw new Error('YDB_STATIC_CREDENTIALS_ENDPOINT is not set and no connection string was provided. ' +
'Either set YDB_STATIC_CREDENTIALS_ENDPOINT or pass the connection string to EnvironCredentialsProvider.');
}
endpoint = new URL('/', connectionString).href;
}
debug.log('YDB_STATIC_CREDENTIALS_USER is set, using static credentials for user: %s, endpoint: %s', username, endpoint);
return new StaticCredentialsProvider({ username, password }, endpoint, this.secureOptions);
}
debug.log('no credentials env vars detected, using anonymous auth');
return new AnonymousCredentialsProvider();
}
}
//# sourceMappingURL=environ.js.map