1

I am working on an application which has an architectural description as below,

  1. There is a docker container, lets say Microservice-A, in which multiple processes are running. Each process is responsible for executing a workflow and is managed by the respective team. All of these processes run with the admin user.
  2. The folder used by the processes is common and people working on of the workflow can see the details of the other process in a production/non-production environment.
  3. As a part of workflow execution, My process makes a network call to one of the microservice, say microservice-B, which is also managed by us.

Problem statement:

  1. As of today, the self-signed certs used to authenticate and communicate with microservice are in a common directory inside the main docker container, microservice-A.
  2. Hence, it is a vulnerability issue, where other services can use the same certs to connect.
  3. My workflow is written in python, hence, it is again possible to sniff (in case of an intruder) the logic and locate the certs directory and use them.

What are some possible ways (including docker constructs) which I can use to rightfully tell my second microservice-B that the call is made from the rightful process running inside the microservice-A. Is there a way I can add a thumbprint to the certs and send the same thumbprint along with the certs during authentication with Microservice-B (Note: I can modify the logic inside the Microservice-B to validate)?

Some points I came up with

  1. Use a PAKE based algorithm to register MS-A with MS-B. Later, a combination of PAKE-key+Certs can be used for communication. But the problem is, if MS-A restarts the PAKE-Key will be lost if it is being created runtime. If Created or saved somewhere then it's the same problem again.
  2. Use a Binary to generate the PAKE-key in runtime. Since logic inside the binary won't be visible, the PAKE-key can be generated on the basis of a static-string stored in the binary itself. But the problem is, I do not want anyone else to execute the binary other than the valid process inside MS-A. Is there any Linux or docker-based construct to uniquely identify the process (Note Pid can change over restart) such that only the valid process inside MS-A is able to execute that binary?
4
  • Do you use a docker orchestration platform (like kubernetes or docker swarm) or it's just plain docker containers running on a linux box? If you're using an orchestration platform, which one do you use?
    – user284677
    Commented Nov 30, 2022 at 6:52
  • Its a plain docker container on a linux.
    – HelloWorld
    Commented Nov 30, 2022 at 8:29
  • when your process (inside microservice-A) makes a call to microservice-B, B runs on the same or a different box?
    – user284677
    Commented Nov 30, 2022 at 11:26
  • As of now, both microservices are inside the same platform.
    – HelloWorld
    Commented Nov 30, 2022 at 11:36

3 Answers 3

0

Put each service to a separate container. This is one of the purposes of containers - isolation. Then provide certificate and key to the container via TLS secrets of Kubernetes.

2
  • If I do that, then only difference would be that the process/services are now running on a different container. Since, the containers cant be password protected, afaik, one can again login and sniff the certs.
    – HelloWorld
    Commented Nov 30, 2022 at 5:57
  • Each container can see only secrets assigned to this container / pod. Normally you create many sets of secrets and assign each set of secrets to the corresponding service (i.e. to a container type). Then containers with service A will see only secrets of set A, containers of service B will see only secrets from set B, etc.
    – mentallurg
    Commented Nov 30, 2022 at 8:41
0

In your comments you mention that you run docker containers without an orchestrator (e.g. kubernetes or docker swarm). I assume that you've taken all the security measures required to avoid having the docker server be used as a priviledge escalation mechanism (or, perhaps, run rootless containers?).

Having said that, as a general rule if an intruder gains admin level privileges all bets are off; there's little you can do to contain the damage, be it modifying binaries, containers or certificates.

If, however, you want to protect the processes (inside your containers) against other processes and/or non-priviledged users, then you could:

  • run each container as a non-admin user (described in one of the links I provided above) and use the correct permissions on the private key files in order to protect them from a non-permitted user/process reading them (assuming that you also have the private keys stored in the same directory). This, of course, means that the processes inside the same container will be able to read all certificates assigned to the user under which the container runs, so perhaps putting one process per container is a good idea
  • run a distro-less container; this way an intruder won't be able to connect to your containers and use shells or other programs to gain valuable info. You can use this technique in combination with running a statically linked binary, which may also include the private key/cert in the code if you want to avoid having them in the common directory

[...] I can use to rightfully tell my second microservice-B that the call is made from the rightful process [...]

When it comes to tampering from a user with the appropriate permissions, this is very difficult to achieve, especially without the proper hardware that may help in certain cases (see remote attestation). In every other case, you can configure properly your processes to use mTLS to achieve mutual authentication.

0

So at the moment you're running multiple microservices on a single host using Docker containers. In this environment you don't need to have any "public" networking running, you can just use a standard Docker bridge network for communications.

That should get rid of the risk of network based attacks. For an attacker to sniff the Docker bridge, they'd need to be running a process locally on the host with privileges (root or NET_ADMIN/NET_RAW capabilities) at that point your security is pretty much shot anyway.

If you're looking to protect one container from users on the host, you're into confidential computing territory, which isn't trivial.

A better option if you have untrusted users on the host, would be to move to an architecture that doesn't :)

Once you scale this up and start talking about different hosts (e.g. using Kubernetes) then the problem of service to service identification/authentication usually falls to something like a service mesh. Istio or Linkerd are common choices here.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .