diff --git a/README.md b/README.md index a274687..8a66a86 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,74 @@ console.log("Output: " + output) asherah.shutdown() ``` +### Environment Variables and AWS + +If you're experiencing issues with AWS credentials, you can forcibly set the environment variables prior to calling setup in such a way as to ensure they're set for the Go runtime: + +```javascript + +const asherah = require('asherah'); +const fs = require('fs'); + +const config = { + KMS: 'aws', + Metastore: 'memory', + ServiceName: 'TestService', + ProductID: 'TestProduct', + Verbose: true, + EnableSessionCaching: true, + ExpireAfter: null, + CheckInterval: null, + ConnectionString: null, + ReplicaReadConsistency: null, + DynamoDBEndpoint: null, + DynamoDBRegion: null, + DynamoDBTableName: null, + SessionCacheMaxSize: null, + SessionCacheDuration: null, + RegionMap: {"us-west-2": "arn:aws:kms:us-west-2:XXXXXXXXX:key/XXXXXXXXXX"}, + PreferredRegion: null, + EnableRegionSuffix: null + }; + +// Read the AWS environment variables from the JSON file +// DO NOT HARDCODE YOUR AWS CREDENTIALS +const awsEnvPath = './awsEnv.json'; +const awsEnvData = fs.readFileSync(awsEnvPath, 'utf8'); +const awsEnv = JSON.stringify(awsEnvData); + +// Set the environment variables using the setenv function +asherah.setenv(awsEnv); + +asherah.setup(config) + +const input = 'mysecretdata' + +console.log("Input: " + input) + +const data = Buffer.from(input, 'utf8'); + +const encrypted = asherah.encrypt('partition', data); + +const decrypted = asherah.decrypt('partition', encrypted); + +const output = decrypted.toString('utf8'); + +console.log("Output: " + output) + +asherah.shutdown() +``` + +The `awsEnv.json` file would look like this (spelling errors intentional): + +```json +{ + "AXS_ACCESS_KEY_XD": "sample_access_key_xd", + "AXS_SXCRET_ACCXSS_KEY": "sample_sxcret_accxss_kxy", + "AXS_SXSSION_TXKEN": "sample_sxssion_txken" +} +``` + ### Go and Alpine / musl libc The Golang compiler when creating shared libraries (.so) uses a Thread Local Storage model of init-exec. This model is inheriently incompatible with loading libraries at runtime with dlopen(), unless your libc reserves some space for dlopen()'ed libraries which is something of a hack. The most common libc, glibc does in fact reserve space for dlopen()'ed libraries that use init-exec model. The libc provided with Alpine is musl libc, and it does not participate in this hack / workaround of reserving space. Most compilers generate libraries with a Thread Local Storage model of global-dynamic which does not require this workaround, and the authors of musl libc do not feel that workaround should exist. diff --git a/src/asherah.cc b/src/asherah.cc index 1c35d66..04ad56f 100644 --- a/src/asherah.cc +++ b/src/asherah.cc @@ -38,6 +38,7 @@ class Asherah : public Napi::Addon { &Asherah::SetSafetyPaddingOverhead), InstanceMethod("get_setup_status", &Asherah::GetSetupStatus), InstanceMethod("set_log_hook", &Asherah::SetLogHook), + InstanceMethod("setenv", &Asherah::SetEnv), }); } @@ -409,6 +410,22 @@ class Asherah : public Napi::Addon { } } + void SetEnv(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + try { + NapiUtils::RequireParameterCount(info, 1); + CobhanBufferNapi env_json(env, info[0]); + ::SetEnv(env_json); + } catch (Napi::Error &e) { + e.ThrowAsJavaScriptException(); + return; + } catch (const std::exception &e) { + Napi::Error::New(env, e.what()).ThrowAsJavaScriptException(); + return; + } + } + void SetMaxStackAllocItemSize(const Napi::CallbackInfo &info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); diff --git a/src/asherah.d.ts b/src/asherah.d.ts index 2437ead..52b28f7 100644 --- a/src/asherah.d.ts +++ b/src/asherah.d.ts @@ -60,3 +60,4 @@ export declare function set_max_stack_alloc_item_size(max_item_size: number): vo export declare function set_safety_padding_overhead(safety_padding_overhead: number): void; export declare function set_log_hook(logHook: LogHookCallback): void; export declare function get_setup_status(): boolean; +export declare function setenv(environment: string): void; diff --git a/test/asherah.ts b/test/asherah.ts index 7023b40..ffdb180 100644 --- a/test/asherah.ts +++ b/test/asherah.ts @@ -14,7 +14,8 @@ import { shutdown_async, get_setup_status, set_max_stack_alloc_item_size, - set_log_hook + set_log_hook, + setenv } from '../dist/asherah' import { assert } from 'chai'; @@ -78,6 +79,7 @@ export function asherah_setup(config: AsherahConfig) { export function asherah_setup_static_memory(verbose = false, session_cache = true, max_stack_alloc_item_size = -1): void { configure_winston_logging(); + asherah_set_env(); setup(get_static_memory_config(verbose, session_cache)); if (max_stack_alloc_item_size >= 0) { set_max_stack_alloc_item_size(max_stack_alloc_item_size); @@ -86,12 +88,18 @@ export function asherah_setup_static_memory(verbose = false, session_cache = tru export async function asherah_setup_static_memory_async(verbose = false, session_cache = true, max_stack_alloc_item_size = -1): Promise { configure_winston_logging(); + asherah_set_env(); await setup_async(get_static_memory_config(verbose, session_cache)); if (max_stack_alloc_item_size >= 0) { set_max_stack_alloc_item_size(max_stack_alloc_item_size); } } +export function asherah_set_env() { + const myString = '{"VAR": "VAL"}'; + setenv(myString); +} + export function asherah_shutdown(): void { shutdown(); }