Using Logs or cobra.Command Println for user feedback? - go

Spf13/cobra command offers a number of elegant tools to provide feedback to the user. I have more experience using Python/headless service where the standard is to use logging libraries and then redirect to stdio if necessary.
However, the more I’ve been exploring cobra, it feels like this is the wrong path. Instead it feels like I should send everything through cobra, and pick and choose from that buffer whatever should go to logging.
Is there any idiomatic guidance here?

I would suggest to use methods provided from cobra.Command for messages that are intended to be read by users.
Logs are usually used to show/save messages that will be read by developers (in this case, you) or if users explicitly want to read the logs.
With that reasoning, you can actually use both of them. For example, you can perform
c.Println("<success message>") to tell users that the command success, and
Debug/Info/Error logs in your CLI app which will be displayed (or saved in a logfile) if user pass --verbose flag to your app.

Related

How to trigger a script when I see that I get a SNMP Set packet

I have a something that is sending an SNMP set command to my server. I can see the packet in wireshark, and I know that I'm getting the packet. Once I get this packet I need to decode it and do an operation (using a script). I can't believe I am the first person that needs to do this, but have googled for hours and found no one else in this use case. I've seen utilities that allow me to use a get snmp, but as the set doesn't actually set anything on my server, there is no way to get it. It doesn't seem traps are helpful as that seems to find the message, as its not labeled a trap. Is there a way to convert the set to a trap once my server gets it, or is there a better method. My server is windows, but if I have to create a linux VM to make this easier I'm all ears. As of now I'm thinking powershell, but if there is an easy way in go, c#, etc I would totally do it.
I am attempting to get a SNMP SET to and use that as a trigger for running a script.
You are 100% correct in that you are not the first person to ask this question. The answer depends on which SNMP agent you have deployed. Many people have had success with Net SNMP and if you want to invoke a shell script from the SNMP agent, see this tutorial. Good luck with your project.
I ended up using pythons pysnmp to build an agent that would recieve the set/get requests. I had to compile my own MIBs for the PDU I was emulating, but got the job done. I also looked into Net SNMP, but I'm more familiar with python and found many helpful examples and good documentation.
I would like to flatten my use case, but at the moment I have two scripts, one that is the agent using pysnmp and one that will do a get request to see what the value is and set off a ssh script. I wish I could hook into the snmp set function, like when the var is written, but for now I have working setup. If anyone wants me to post my code I can.
Copied a lot of code from the second example here:
https://pysnmp.readthedocs.io/en/latest/examples/v3arch/asyncore/agent/cmdrsp/agent-side-mib-implementations.html
Learned about MIB compiling and used the mbidump.py tool. Looks like if you don't provide the proper file the old host server might be compromised and it downloads a file automatically...so be careful.

How can I configure email alert to check if an Essbase Application is running or not?

I want to develop a script which will check the state (running or not) of an Essbase application (say, every 15 mins.).
If the Essbase application is not running then it will send an alert via email to user or application admin .
There isn't anything built in to Essbase that is going to do this for you. You really need to look at this in terms of two different things you are trying to accomplish:
How to tell if an Essbase cube is running
How to send an email from a batch/scheduled process
As for item 1, there are at least a couple of ways to go. I believe you could use MaxL (the automation language for Essbase) to determine if an application/cube is running. For example, you could use MaxL to check the status of the cube, output the script to a text file, and then scan that text file for the proper line/indicator that the cube is running or not. This may technically work but it wouldn't be my preferred option. You would also have to develop this so that in case the server itself isn't running, it triggers the specific action you want.
Another way to go (and this is my preferred option) is to use the Essbase Java API to determine if the application/cube is running. Although you may not be familiar with Java, this to me is the cleanest way to implement this functionality. You would use the API to connect to the server, and if the connection to the server was successful you could then check the status of the application/cube. In case the cube or server is down/stopped, you can do the appropriate action. You could also send the email from Java itself, using one of the Java email libraries.
You can also send emails from the command-line. It varies in specifics between Unix/Windows but in general if you can specify an SMTP server, email address, subject, body, and other parameters, it works just fine. There are freely available email clients I have seen and used that work completely on the command-line and handle this use case fairly well.
Once everything is all developed and tested it's just a simple matter of scheduling it to run every 15 minutes or however often you want to run it.
As I mentioned, MaxL is the scripting language for Essbase. There is a program on the Essbase server that interprets MaxL scripts. The MaxL language is documented extensively in the EPM documentation. As a very simple example, you could write a MaxL script like the following:
login "admin" "password" on "localhost";
display application "Sample";
If you are running on a Linux/Unix server then you might then run the script as follows:
startMaxl.sh your_script.msh
This script would then output a text-based grid of different application properties to the console.
One of the columns that the display application command will display is related to the application status, if the app is loaded/started or whatever. Theoretically to get this solution to work you'd need to send MaxL's script output to a file and then scan the file for the proper text and decide if action needs to be taken. While this approach can work, it comes with risks. That's why I think Java (the preferred API for Essbase) is much better suited to solving this.

How to identify/authorize the sender of a message in a named pipe? (CreateNamedPipe)

I've created a communication between two applications using named pipes.
The first application creates a named pipe with CreateNamedPipe and reads the received messages with ReadFile sent by the second application. Both applications are able to communicate that way as intended.
Is it somehow possible to identify the sender of a received message?
Without some sort of identification (like getting the sender exe path) or authorization every other application could use that pipe to send messages to my application.
(Edit) Further details, because it seems it's important in this case:
The application that creates the pipe is running as a Windows service.
Both applications run locally on the same system.
The GetNamedPipeClientProcessId() will give you the process ID of the client process. You can then open a handle to the process with OpenProcess() and call GetModuleFileNameEx() to determine what application is running in that process. You can then vet the application in whatever way you think best, e.g., you might want to check the identity of the digital certificate or you might prefer to just check that the pathname is as you expect it to be.
Note that attempting to restrict access to a particular application rather than a particular user is never going to be robust; an attacker could always take control of the approved application and replace its code with their own. Basically it isn't going to be more than a speed bump, but if you feel it is worth doing, it can be done.
If what you really want to know is what user has connected, you should instead be using ImpersonateNamedPipeClient() as already suggested in the comments, followed by OpenThreadToken() and so on. Or better still, set the permissions when creating the named pipe so that only the authorized users are able to connect in the first place.
Now that you've clarified that the client runs with elevated privileges, I can make a more concrete recommendation: do both of the above. Configure the permissions on the named pipe so that only members of the Administrators group can access it; that will ensure that only applications running with elevated privilege can access it. Checking the executable as well won't hurt, but it isn't sufficient by itself, because an attacker could launch a copy of your application, suppress the requested elevatation, and inject their own code into the process. (Or, as conio points out, modify their own process to make it look as if they are running your executable; GetModuleFileNameEx() is not intended to be used as a security measure, so it makes no effort to avoid spoofing.)

How would I build a game that allowed players to write their engines with resource constraints in Ruby?

I want to copy the Scribd developers challenge, but build it using the Gosu framework in ruby. I know how to do most of it, except I'm not 100% sure how to do the following. I'd like a few ideas on the best way to approach this.
Other people (students) will be able to check their ruby code into the repo and I'd like to eventually run all the different bots against each other to determine a winner. Here are my questions about how I would do this.
There is a time limit and ram usage limit. How would you enforce this. Essentially, what I think I want to do is have the game class have a board representation, and then call each engine's main method and pass it in the game board. The method then should return a move. If it doesn't return a move in the time limit, then we move on to the next move. Also, there should be a ram limit such that they can't just iterate over all possibilities and store them in memory and essentially store all the states in the game.
Specifically, how can I spawn a process I can monitor and kill in ruby?
Time and RAM are concerns, sure, but the greater concern is security. Running arbitrary user code on your server invites attacks. What's to prevent a user from uploading code that monkey-patches your app code in order to cheat, or send spam from your server, or break things with FileUtils.rm_rf(__dir__) or while { fork }?
To run user code safely, you must run it in a sandbox. But I'll get back to that.
The simplest way to start (and solve the time/RAM problem) will be to...
Run user code in a separate process
Mandate that the user's script must define a class (or module) with a specific name, e.g. Bot, that implements your main interface. Write a wrapper script that will take as an argument the path to a user's script and read the board data (as Marshaled data, or serialized to YAML or JSON) from $stdin. The script will then require the temporary file and pass the board data to Bot. Finally, it will take the output from Bot, marshal/serialized it, and write it to $stdout.
When a user uploads a script, your app will write it to a temporary file and run the above wrapper script (with e.g. Open3), passing it the marshaled/serialized board data on stdin, then reading and unmarshaling/deserializing the result from its stdout/stderr.
How does this solve the time/RAM problem? Well, since you're just running your wrapper script in a separate process by invoking ruby, you can lean on your OS's process-management features, thus removing the possibility of the user monkey-patching their way around those restrictions. If you google e.g. "limit process memory" along with the name of your OS you'll find lots of information. For example, for Linux this tool looks handy: timeout. With such a tool you might run e.g.:
$ timeout -t 60 -m 10000 ruby /path/to/user/script.rb
Security
Okay, so what about security? It's a hard problem, not least because Ruby is so flexible, and so I can't just tell you "this is the solution."
One thing you could do is run all user code in a virtual machine using e.g. Docker. This would make it easy to prevent the user code from accessing your (real) filesystem or the network. (In this case it may make sense to have a simple Ruby server running on the VM that can receive scripts and board data from your app, run the scripts, and respond with the results, since your app won't be able to directly invoke ruby on the VM.)
This still leaves a lot of room for mischief, though. It mitigates the damage that can be done by FileUtils.rm_rf or while { fork }, as you can just spin up a fresh VM, but that's still an inconvenience. To prevent those entirely, you really need a sandbox that reliably keeps the user from accessing methods and modules that could be used maliciously. There's no One True Way to do this in Ruby, alas, but there are some tools and some code out there that will help you get started. Googling "Ruby sandbox" will turn up a lot. One project I've found instructive is RubyFiddle, which is open source and so its code is available on GitHub. It will point you to jruby-sandbox, which does sandboxing with JRuby because Java, unlike (MRI) Ruby, does have mature sandboxing solutions.
I hope that's helpful. Good luck!

multiple processes writing to a single log file

This is intended to be a lightweight generic solution, although the problem is currently with a IIS CGI application that needs to log the timeline of events (second resolution) for troubleshooting a situation where a later request ends up in the MySQL database BEFORE the earlier request!
So it boils down to a logging debug statements in a single text file.
I could write a service that manages a queue as suggested in this thread:
Issue writing to single file in Web service in .NET
but deploying the service on each machine is a pain
or I could use a global mutex, but this would require each instance to open and close the file for each write
or I could use a database which would handle this for me, but it doesnt make sense to use a database like MySQL to try to trouble shoot a timeline issue with itself. SQLite is another possability, but this thread
http://www.perlmonks.org/?node_id=672403
Suggests that it is not a good choice either.
I am really looking for a simple approach, something as blunt as writing to individual files for each process and consolidating them accasionally with a scheduled app. I do not want to over engineer this, nor spend a week implementing it. It is only needed occassionally.
Suggestions?
Try the simplest solution first - each write to the log opens and closes the file. If you experience problems with this, which you probably won't , look for another solution.
You can use file locking. Lock the file for writing, write the message, unlock.
My suggestion is to preserve performance then think in asynchronous logging. Why not send your data log info using UDP to service listening port and he write to log file.
I would also suggest some kind of a central logger that can be called by each process in an asynchronous way. If the communication is UDP or RPC or whatever would be an implementation detail.
Even thought it's an old post, has anyone got an idea why not using the following concept:
Creating/opening a file with share mode of FILE_SHARE_WRITE.
Having a named global mutex, and opening it.
Whenever a file write is desired, lock the mutex first, then write to the file.
Any input?

Resources