Skip to main content
  1. Posts/

Sandboxing with Podman and IO

·435 words·3 mins·
Author
Agent IO
Table of Contents
Lock down and control your application's network traffic.

Using networking features of Podman, we can sandbox applications so that the only outbound connections they make go through IO.

Here's a quick demonstration. To emulate our application, we'll use the curl container image.

Let's exercise it by curling a public URL:

$ podman run --rm -it docker.io/curlimages/curl https://agent.io/hello.json
{"message":"hello!"}

To sandbox our curl, we'll create an internal Podman network and use it to make the request.

# create the internal network
podman network create --internal secure-internal

# this curl invocation will fail
podman run --rm -it --network secure-internal docker.io/curlimages/curl https://agent.io/hello.json
curl: (6) Could not resolve host: agent.io

Now let's set up an IO to call our remote URL. We'll use a calling configuration:

calling "agentio" {
  name   = "Agent IO"
  target = "agent.io"
  port   = 4000
  operation "get-hello" {
    method = "GET"
    path = "/hello.json"
  }
}

To this we'll add our IO license key and an SSH key to allow us to connect to our IO over SSH.

license = "eyJhbGciO..."
user "tim@agent.io" {
  name       = "Tim Burks"
  public_key = "ssh-ed25519 AAAA..."
}

Put these files in a directory called io and run the IO image once with Podman to initialize the IO database.

podman run --rm -v ./io:/io ghcr.io/agentio/io:latest -c ./io/license.hcl -c ./io/users.hcl -c ./io/agentio.hcl -x

Now we can create a public network and attach our IO container to both of our networks.

# create the internal network
podman network create --internal secure-internal

podman run --name myio --network public-bridge --network secure-internal -p 2200:2200 -v ./io:/io ghcr.io/agentio/io:latest

Now rerun our curl command with the internal network and send the request to our IO container.

$ podman run -it  --net secure-internal docker.io/curlimages/curl http://myio:4000/hello.json
{"message":"hello!"}

We can also connect to our IO using Linux abstract sockets, but only if we run our container in the network environment of our IO.

podman run -it  --net container:myio docker.io/curlimages/curl http://anything/hello.json --abstract-unix-socket io-calling-agentio
{"message":"hello!"}

Unfortunately this breaks our sandbox and allows our curl to see outside the container.

$ podman run -it  --net container:myio docker.io/curlimages/curl https://agent.io/hello.json
{"message":"hello!"}

So for now we happily use TCP networking to make requests from our sandboxed app.

You might have noticed that only GET requests to /hello.json are allowed. This is because our calling configuration only mentions that one specific operation. When we specify at least one operation, all others are blocked.

$ podman run -it  --net secure-internal docker.io/curlimages/curl http://myio:4000
GET / is not allowed

$ podman run -it  --net secure-internal docker.io/curlimages/curl http://myio:4000/hello.json -X PUT
PUT /hello.json is not allowed

We can view our traffic by connecting to our IO over ssh:

ssh localhost -p 2200