📜 ⬆️ ⬇️

Displaying Environment Variables in Redis


Redis is a key-value store. Environment variables - resemble the same. And what if it somehow combine?


For fans of Friday's posts, easy hacking and strange desires - I ask under the cat


There is an impressive list of client libraries for Redis in almost all programming languages. But what if:


  1. there are already existing applications that are not good to change;
  2. you need / want to make an application that can work with and without Redis;
  3. simpler is better Quite often, working with a cache is purely auxiliary and introduces unnecessary complexity into the application.

In my case, the task arose after the creation of the next CGI-like service, which needed to save state. In this case, the execution of this script can occur on different machines.


Since it was about 2 o'clock in the morning and it was already Friday for me, it was decided to relax and do something simple and interesting.


Question and idea


Is it possible to intercept system calls so that when writing to environment variables ( setenv ), the data
recorded in Redis, and when reading ( getenv ) on the contrary got it from a cache?


Schematically looks like this:


 Application <-- [syscall]--> [Wrapper] <-- [GET/DEL/...] --> [Redis] 

Study


Is it possible


Yes, there is a good article that describes how to make system call interceptors.


Someone has to initialize the connection ...


There is an unpopular opportunity to specify the functions of initialization (constructor) and finalization (destructor) in the shared library. In them we will connect.


Implementation


It was necessary to study the POSIX'a and Linux'a specification on this topic.


Functions that needed to be intercepted:



The code is here .


Dependencies



Assembly


No dirty tricks - typical CMake from Github


Dependencies


 sudo apt install libhiredis-dev cmake build-essential 

Assembly


 git clone https://github.com/reddec/envredis.git cd envredis mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release ../ && make 

Using


Important point: some applications do not change the environment variables, but only the internal array. In such applications, the data from Redis will be received, but will not be displayed back.


A good option is python. According to the documentation , the change in os.environ displayed in the environment variables.


Let's say Redis is already raised on the local machine.



 $ python -c 'import os; print("XYZ=" + os.environ.get("XYZ", ""))' #   : # XYZ= 


 $ redis-cli SET XYZ "Hello world" #   : # OK 


 LD_PRELOAD=/path/to/libenvredis.so python -c 'import os; print("XYZ=" + os.environ.get("XYZ", ""))' #   # XYZ=Hello world 


 LD_PRELOAD=/path/to/libenvredis.so python -c 'import os; os.environ["SAY"] = "Bye!"' 


 redis-cli GET SAY #   # "Bye!" 

PS


The task took about two hours, taking into account the study of the subject area. Made more for fun than for real purposes.


Nevertheless, someone may come in handy.



')

Source: https://habr.com/ru/post/344766/


All Articles