Nodejs - Windows Key/Certificate store - windows

Does anybody have any pointers as to how I could go about interacting with the Key/Certificate store using nodeJs? I specifically want to add/remove certificates and possibly keys.
Update.
So the way to go here is to use "edge". Very nice work!
https://github.com/tjanczuk/edge

Without knowing too much about your setup here is a stab at a 'pointer' as to how to interact.
You could try using Nodes Child Process and then spawning out a process to the commandline and interact with the key/certificate store the way you would via command line. Microsofts certificate manager tool perhaps?
Rough example:
var exec = require('child_process').exec,
child;
child = exec('certmgr /add /all /c myFile.ext newFile.ext',
function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});

I've just published node-windows-root-certs which uses ffi to read the windows root certificate store, and then apply these in nodejs... may provide some inspiration.
Example use to use Windows certificates rather than internal NodeJS certificates:
var windowsRootCerts = require('node-windows-root-certs');
// to read the windows root certs and patch in a single command:
windowsRootCerts.useWindowsCerts();

There is an npm package 'windows-certs' which uses edge and a .csx script to read certificates in .pem format
https://github.com/jfromaniello/node-windows-certs
https://www.npmjs.com/package/windows-certs
This should have the required functionality, but is marked as deprecated. The successor package is indicated as.win-ca. However, this seems to be lacking some of the functionality of the older package:
https://www.npmjs.com/package/win-ca
https://github.com/ukoloff/win-ca

Related

JXcore native app as windows service

I make a simple echo server that i want to run as service under windows.
here's the code
var fs=require('fs');
var net = require('net');
var server = net.createServer(function(c) { //'connection' listener
console.log('client connected');
c.on('end', function() {
console.log('client disconnected');
});
c.write('hello\r\n');
c.pipe(c);
});
server.listen(8124, function() { //'listening' listener
console.log('server bound');
});
var fd=fs.openSync('log.txt', 'a');
fs.writeSync(fd, 'START\r\n');
fs.closeSync(fd);
process.on('SIGINT', function (par){
var fd=fs.openSync('log.txt', 'a');
fs.writeSync(fd, 'SIGINT ('+par+")\r\n");
fs.closeSync(fd);
process.exit(1);
});
process.on('exit', function (code){
var fd=fs.openSync('log.txt', 'a');
fs.writeSync(fd, 'EXIT ('+code+")\r\n");
fs.closeSync(fd);
});
Next i compiled with JXcore like:
jx package echoserver.js "echoserver" -native
Then the executable run from console or explorer double click and do its job! GOOD!
Now, with sc windows tool, i create a service
sc create echosvr full_path_to\echoserver.exe
And the echosvr is now correctly listed in services tab of windows taskmanager.
The bad comes now: i try to start the service in several way, but i get always a message that tells me that the service did not respond to the start or control request in a timely fashion.
what i miss?
Any suggestion?
I got it!
I downloaded nssm and moved the one executable (the 32bit one, just to try) in the windows dir, I run from command prompt the nssm.exe and configured the service as explained in the nssm link.
> nssm install echosvr
this opened a popup window for configuration, where i put my needs..
then:
> net start echosvr
and the server starts! Now it is visible in task manager services tab.
I stopped the service from task manager and the log file was like:
START
SIGINT (undefined)
EXIT (1)
That's what I need, because it signal a graceful close request!
To deploy a solution like this, nssm offers a command line setup that i will surely use!
(PS: It doesn't support service pause/resume, but this can be acceptable..)

Portable Browser Issues when deploying R Shiny App

I've built a complex Shiny interface that pulls from an internally networked ODBC table and allows a user to interact with the data through their browser. The company is on Windows 7 Enterprise and IT only supports IE 9. Some users have chrome installed in their user folders, some have firefox, some use IE 9. I followed a tutorial from R-Bloggers (here: http://www.r-bloggers.com/deploying-desktop-apps-with-r/) and it runs on my machine using a portable Chrome browser downloaded from PortableApps.com. Great. Unfortunately the interface has not started on ANYONE else's machine that has their own local Chrome browser installed.
Following the tutorial, I use the following vb script:
Rexe = "R-Portable\App\R-Portable\bin\Rscript.exe"
Ropts = "--no-save --no-environ --no-init-file --no-restore --no-Rconsole"
RScriptFile = "runShinyApp.R"
Outfile = "ShinyApp.log"
strCommand = Rexe & " " & Ropts & " " & RScriptFile & " 1> " & Outfile & " 2>&1"
intWindowStyle = 0 ' Hide the window and activate another window.'
bWaitOnReturn = False ' continue running script after launching R '
CreateObject("Wscript.Shell").Run strCommand, intWindowStyle, bWaitOnReturn
This script calls the following code in my R file:
message('library paths:\n', paste('... ', .libPaths(), sep='', collapse='\n'))
chrome.portable = file.path(getwd(),'GoogleChromePortable/App/Chrome-bin/chrome.exe')
launch.browser = function(appUrl, browser.path=chrome.portable) {
message('Browser path: ', browser.path)
shell(sprintf('"%s" --app=%s', browser.path, appUrl))
}
shiny::runApp('shiny', launch.browser=launch.browser)
It works on my computer just fine... I DO have chrome installed locally, but I'm calling the Portable Chrome executable. It worries me that the two are sharing prefs or something, e.g. I notice that a hash from the Preferences file in my installed version, specifically:
"chrome_url_overrides": {
"bookmarks": [ "chrome-extension://eemcgdkfndhakfknompkggombfjjjeno/main.html" ]
},
...matches the same json entry from the Portable Chrome installation:
"chrome_url_overrides": {
"bookmarks": [ "chrome-extension://eemcgdkfndhakfknompkggombfjjjeno/main.html" ]
}
Why do these long random strings match? Am I barking up the wrong tree for wondering about this? I don't know why these strings match if they are two separate installations of Chrome executables, one of which is supposed to run completely independently from anything on the machine.
Here's a set of errors from one machine:
.../Desktop/TestApp3/GoogleChromePortable/App/Chrome-bin/chrome.exe[9100:9408:0716/141934:ERROR:gpu_info_collector_win.cc(103)] Can't retrieve a valid WinSAT assessment.
[9100:9408:0716/141934:ERROR:component_loader.cc(138)] Failed to parse extension manifest.
[9100:1716:0716/141946:ERROR:get_updates_processor.cc(214)] PostClientToServerMessage() failed during GetUpdates
Here's a set of errors from a second machine:
.../Documents/TestApp3/GoogleChromePortable/App/Chrome-bin/chrome.exe
[5220:3384:0714/142128:ERROR:component_loader.cc(138)] Failed to parse extension manifest.
[5220:7600:0714/142130:ERROR:external_registry_loader_win.cc(136)] File C:\Program Files\Coupons.com CouponBar\chrome\Coupons.com.crx for key
Software\Google\Chrome\Extensions\cnpkmcjgpcihgfnkcjapiaabbbplkcmf does not exist or is not readable.
[5220:2120:0714/142140:ERROR:get_updates_processor.cc(214)] PostClientToServerMessage() failed during GetUpdates
[5220:3384:0714/142413:ERROR:CONSOLE(122)] "Could not find value for secondaryUser", source: chrome://resources/js/load_time_data.js (122)
[5220:3384:0714/142413:ERROR:CONSOLE(122)] "[undefined] (secondaryUser) is not a boolean", source: chrome://resources/js/load_time_data.js (122)
[5220:3384:0714/142425:ERROR:CONSOLE(122)] "Could not find value for secondaryUser", source: chrome://resources/js/load_time_data.js (122)
[5220:3384:0714/142425:ERROR:CONSOLE(122)] "[undefined] (secondaryUser) is not a boolean", source: chrome://resources/js/load_time_data.js (122)
[5220:3384:0714/142442:ERROR:navigation_entry_screenshot_manager.cc(167)] Invalid entry with unique id: 12
It seems like Chrome is doing different things on different computers and is not actually acting as a standalone browser... but likely interacting with the browser installed on their respective computers via the registry or some other "under the hood, active" communication. Maybe, since I installed the portable executable on my machine, a bunch of my local extensions or preferences were automatically updated to the portable's preferences, etc. and subsequently this is causing a conflict on every other machine??
Can I shutdown Chrome's extensions or extra functions like the calls to the updater? Is there a better standalone portable browser that functions well with Shiny for this type of "deployment" purpose? Can I fix this or is this a lost cause?? This should be obvious but I'll say it anyway: it is definitely not economically efficient to ask the non-technical types to install R, then RStudio, then confirm their working directory structure, then call the runApp() command via the Script window...
I started with those same articles, but developed the RInno package to solve this exact problem, i.e. when you want to share your desktop Shiny app with non-technical users who can't be expected to mess around with all those details.
To get started:
install.packages("RInno")
require(RInno)
RInno::install_inno()
Then you just need to call two functions to create an installation framework:
create_app(app_name = "myapp", app_dir = "path/to/myapp")
compile_iss()
This will create an installation wizard that runs like any other program, but installs your shiny app on a Windows desktop computer. If you would like to include R for your co-workers who don't have it installed, add include_R = TRUE to create_app:
create_app(app_name = "myapp", app_dir = "path/to/myapp", include_R = TRUE)
It defaults to include shiny, magrittr and jsonlite, so if you are using other packages like ggplot2 or plotly, just add them to the pkgs argument. You can also include GitHub packages to the remotes argument:
create_app(
app_name = "myapp",
app_dir = "path/to/myapp"
pkgs = c("shiny", "jsonlite", "magrittr", "plotly", "ggplot2"),
remotes = c("talgalili/installr", "daattali/shinyjs"))
If you are interested in other features, check out FI Labs - RInno

Execute git cmd via node.js on windows fails with err

git is installed on windows and works from any directory (it is in System path)
var child_process = require('child_process');
child_process.exec('git --version', function(err, stdout, stderr) {
// stdout is correct - git version 1.7.11.msysgit.1
// but err is not null
// err is [Error: Command failed: ] killed: false, code: 1, signal: null }
}
What can cause this?
I had this issue using Windows 7 with msysgit. Two things seem to solve the issue.
First, verify that your Path system variable includes a path to the Git bin directory, and not the cmd directory:
C:\Program Files (x86)\Git\bin
Next, verify you have a recent version of msysgit. I've verified the issue as solved with version 1.8.4-preview:
https://code.google.com/p/msysgit/downloads/list
Restart your shell and try again.
As a workaround you can pass {env:{PATH:"C:\path to\node"}} as the options argument to process.exec(cmd, opts, callback) as described in docs. I am surprised that the Windows path doesn't carry over but have no explanation why.

Why am i getting a ENOTEMPTY error?

So i create a default meteor app.
Its runs great.
Now I add a simple insert in the startup function.
its is now giving me exceptions.
Here is my app.js code:
Book = new Meteor.Collection("book");
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to app_01.";
};
Template.hello.events({
'click input' : function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
if (Book.find().count() === 0) {
var names = ["Ada Lovelace",
"Grace Hopper",
"Marie Curie",
"Carl Friedrich Gauss",
"Nikola Tesla",
"Claude Shannon"];
for (var i = 0; i < names.length; i++)
Book.insert({name: names[i], score: Math.floor(Math.random()*10)*5});
}
});
}
And here is the exception I am getting:
No dependency info in bundle. Filesystem monitoring disabled.
Errors prevented startup:
Exception while bundling application:
Error: ENOTEMPTY, directory not empty 'C:\Users\Office\Workspace\Code\Meteor\app_01\.meteor\local\build\server'
at Object.fs.rmdirSync (fs.js:456:18)
at Object.module.exports.rm_recursive (C:\Program Files (x86)\Meteor\app\lib\files.js:256:10)
at C:\Program Files (x86)\Meteor\app\lib\files.js:254:15
at Array.forEach (native)
at Function._.each._.forEach (C:\Program Files (x86)\Meteor\lib\node_modules\underscore\underscore.js:79:11)
at Object.module.exports.rm_recursive (C:\Program Files (x86)\Meteor\app\lib\files.js:252:9)
at _.extend.write_to_directory (C:\Program Files (x86)\Meteor\app\lib\bundler.js:493:11)
at Object.exports.bundle (C:\Program Files (x86)\Meteor\app\lib\bundler.js:685:12)
at exports.run.restart_server (C:\Program Files (x86)\Meteor\app\meteor\run.js:615:26)
at C:\Program Files (x86)\Meteor\app\meteor\run.js:726:9
Please fix the problem and restart.
The console gives me no useful information at all.
Some more info:
I am using the windows version of meteor 0.5.4
My code has both tabs and spaces as indentation (should that be a problem?)
to add to my perplexity:
If i run the leaderboard example, it runs perfectly.
When I run the default project with my modified startup code, i get the exception. >.<
More info:
when the server crashed, the mongod service was still running in windows. In my infinite wisdom, i thought I'll kill it and maybe try a fresh restart of it.
now i get a new error:
PS C:\Users\Office\Workspace\Code\Meteor\app_01> meteor
[[[[[ C:\Users\Office\Workspace\Code\Meteor\app_01 ]]]]]
Unexpected mongo exit code 100. Restarting.
Unexpected mongo exit code 100. Restarting.
Unexpected mongo exit code 100. Restarting.
Can't start mongod
MongoDB had an unspecified uncaught exception.
Check to make sure that MongoDB is able to write to its database directory.
Edit: now deleted the .meteor/local/db contents. we are now back to the ENOTEMPTY error.
It is because the directory is not getting deleted during the bundling operation.
So when this happens, Stop your server with ctrl + c.
Then delete the contents of .meteor\local\db directory as well as .meteor\local\builds directory and run the server again using meteor command.
Not an ideal way, but it works.
Just tested this on my mac and on my Windows machine, it works fine for me. (Copied and pasted your code into app.js, did not change anything anywhere else, as I understood this is what you did).
There are two ways to go on:
You try meteor reset. Warning: This will empty any databases you had within this app, but I think there isn't anything all to important in there at the moment?
You delete the app and make a new one using meteor create appname, and copy the source code from above into app.js.
I think investing too much time and effort is not worth it, since it is not an app close to production stage. If, however, creating a new app causes the same problem, it will get interesting =)
EDIT: Just searched around and found this: https://github.com/TomWij/meteor/issues/18
Scroll down to the answer; apparently it might be your antivirus scanner preventing Meteor from rebuilding it. Is that possible?
Also, are you starting Meteor from anything else than cmd.exe? I just read through the issue on GitHub, and things seem to be pretty gnarly when using anything else than cmd.exe (eg the GitHub Bash Shell)
Once my pull request goes in, this issue should be resolved:
https://github.com/TomWij/meteor/pull/56

MACOSX: how to start daemon which need root privileges from cocoa application

Conditions are the following: MacOSX 10.7 and Cocoa graphical application written in objective-c.
I am faced the following problem.
I can't start daemon application from /user/bin folder from my Cocoa application.
I know that I should have root privileges to do that.
I have installer, not *.pkg but manually written installer application. I need to start my daemons after installation process is finished.
How can I increase my privileges level in objective-c application?
I have this code.
But AuthorizationExecuteWithPrivileges call is deprecated.
We should not use it.
AuthorizationItem authItem = { kSMRightModifySystemDaemons, 0, NULL, 0 };
AuthorizationRights authRights = { 1, &authItem };
AuthorizationFlags flags = kAuthorizationFlagDefaults |
kAuthorizationFlagInteractionAllowed |
kAuthorizationFlagPreAuthorize |
kAuthorizationFlagExtendRights;
AuthorizationRef authRef = NULL;
OSStatus status = AuthorizationCreate(&authRights,
kAuthorizationEmptyEnvironment, flags, &authRef);
status = AuthorizationExecuteWithPrivileges(authorizationRef, tool, kAuthorizationFlagDefaults, args, &pipe);
The second way is to use privileged helper.
This way looks very complicated for my case.
I just need to start daemons after install.
Of cource I can ask user to restart mac. But i would like to avoid it.
Other possibility is SUID bit on the daemon executable file.
But it is not secure i think.
My question is:
Is there other simpler way to do it?
Well, there may be an answer here.
You need to:
Create a shell script with your operations.
Create an apple script NSString in which you request the shell script to be executed with administrator privilege.
Create an instance of NSAppleScript and execute the apple script.
Here are more details:
AuthorizationExecuteWithPrivileges is deprecated

Resources