Skip to content

Docker environment

When using Docker environments, each user session runs in a separate Docker container. This is in contrast to the local environment, where each user session runs on the same host as Bifröst.

This is useful if you explicitly do not want to give users access to the host itself, but to environments where they can work with defined toolsets. Especially if you want to create demo or training environments.

But also if you want to set up a Bastion/Jump host, where a user can jump from this server to another network, this can be very helpful. In this case, using different networks can be beneficial.

Configuration

type

Environment Type = "docker"

Has to be set to docker to enable the docker environment.

loginAllowed

bool Authorization = true

Has to be true (after being evaluated) that the user is allowed to use this environment.

Examples

  1. Require that the existing local user has the group ssh:
    1
    2
    3
    4
    5
    loginAllowed: |
       {{ or
           (.authorization.user.group.name | eq "ssh" )
           (.authorization.user.groups     | firstMatching `{{.name | eq "ssh"}}`)
       }}
    

host

string Authorization = "{{ env `DOCKER_HOST` }}"

URL how to connect to the API endpoint of the docker compatible daemon.

Accepted protocols are:

  1. http
  2. https
  3. tcp
  4. unix (only supported on unix based systems)
  5. npipe (only supported on Windows)

If this variable is empty (which can be also the case if {{ env `DOCKER_HOST` }} evaluates to empty, because the environment variable is not set), the system specific connection will be chosen:

  • Unix (such as Linux): unix:///var/run/docker.sock
  • Windows: npipe:////./pipe/docker_engine

apiVersion

string Authorization =

"{{ env \`DOCKER_API_VERSION\` }}"

Defines which version of Docker API should be chosen for communication. In doubt leave this blank.

certPath

"{{ env \`DOCKER_CERT_PATH\` }}"

Is a directory which should contain the following files:

  • key.pem: Private key Bifröst should connect to the Docker API with.
  • cert.pem Certificate Bifröst should present when connect to the Docker API.
  • ca.pem: Certificate authorities to check the certificate of the Docker API Host against.

If this variable is empty (which can be also the case if {{ env `DOCKER_CERT_PATH` }} evaluates to empty) and tlsVerify is set to false, all Docker API Hosts are accepted.

tlsVerify

bool Authorization =

"{{ env \`DOCKER_TLS_VERIFY\` | ne \`\` }}"

If this variable is false (which can be also the case if {{ env `DOCKER_TLS_VERIFY` }} evaluates to empty), all Docker API Hosts are accepted.

Danger

Setting this to false is only recommend, if connecting to the local socket connection (on the same machine - see host's default behavior).

image

string Authorization = "alpine"

Which OCI/Docker image should be used for this environment.

Everything available within this image will be also available to the user who is connecting to the container using this image. Therefore, you should consider to creating your custom images if you need additional features like kubectl, skopeo, ... and use this one here.

This image needs to contain a valid shell executable.

ENTRYPOINT and CMD settings of the image will be ignored.

imagePullPolicy

Pull Policy Authorization = "ifAbsent"

Defines what should happen if the container starts with the required image of the container.

If the image needs to be pulled, it will trigger the image-pull preparation process.

imagePullCredentials

Defines credentials which should be used to pull the defined image.

Examples

  1. Using direct json:
    1
    2
    imagePullCredentials: |
     {"username":"foo","password":"bar"}
    
  2. Using base64 URL encoded json:
    1
    2
    imagePullCredentials: |
     eyJ1c2VybmFtZSI6ImZvbyIsInBhc3N3b3JkIjoiYmFyIn0
    
  3. Using content from file:
    1
    imagePullCredentials: "{{ file `/etc/engity/bifroest/secrets/my-great-secret` }}"
    
  4. Using content from environment variable:
    1
    imagePullCredentials: "{{ env `MY_GREAT_SECRET` }}"
    

networks

[]string Authorization = ["default"]

Defines the container networks this container should be connected to.

Empty always defaults to ["default"].

Note

As long impPublishHost isn't set, the first network should be always reachable by Bifröst itself. This can be either the case if Bifröst itself runs inside of Docker (Bifröst in Docker) or it runs on the host machine and there is a valid route (which is the default Linux native, but not on Docker/Podman for Desktop).

volumes

[]string Authorization

Defines which volumes should be mounted into the container. Each entry is an individual mount statement.

This is the equivalent of -v/--volume flag of Docker. See Bind mounts documentation of Docker about the syntax of these entries.

We recommend to use mounts instead, because it is easier to understand. volumes is the older version of the notation and known by experienced users.

mounts

[]string Authorization

Defines which volumes should be mounted into the container. Each entry is an individual mount statement.

This is the equivalent of --mount flag of Docker. See Bind mounts documentation of Docker about the syntax of these entries.

capabilities

[]string Authorization

List of Unix kernel capabilities to be added to the container. This enables a more fine grained version in contrast to give all capabilities to the container with privileged = true.

Does only work on Unix based systems.

privileged

bool Authorization = false

If this is set to true this container will have all capabilities of the system.

Danger

Only enable this feature if you really need this, and you know what you're doing.

dnsServers

[]string Authorization

Defines a list of external DNS server the container should use.

dnsSearch

[]string Authorization

Defines custom DNS search domains for the container.

shellCommand

[]string Authorization = "<os specific>"

The shell which should be used to execute the user into.

If not defined, the following command will be used:

  • Linux: ["/bin/sh"]
  • Windows: ["C:\WINDOWS\system32\cmd.exe"]

execCommand

[]string Authorization = "<os specific>"

If execute is used, this is the command prefix which will used for the command.

If not defined, the following command will be used:

  • Linux: ["/bin/sh", "-c"]
  • Windows: ["C:\WINDOWS\system32\cmd.exe", "/C"]

sftpCommand

[]string Authorization = "<bifroest sftp-server>"

Defines the sftp server command which should be used. Usually you should not be required to modify this, because by default Bifröst is handling this by itself.

directory

Defines the working directory of the initial process inside the container for each execution.

If not defined the value WORKDIR will be used. If this is absent, too: /.

user

string Authorization

Defines the user will run with inside the container.

If not defined the value USER will be used. If this is absent, too: root.

banner

string Authorization = ""

Will be displayed to the user upon connection to its environment.

Examples

  1. If local user is used, show its name in a message:
    1
    banner: "Hello, {{.authorization.user.name}}!\n"
    
  2. If users authorized via OIDC is used, show its name in a message:
    1
    banner: "Hello, {{.authorization.idToken.name}}!\n"
    

portForwardingAllowed

bool Authorization = true

If true, users are allowed to use SSH's port forwarding mechanism.

impPublishHost

string Authorization

If this property is set, the port of the IMP process will be not just exposed on the container network, but also on this host.

At this address Bifröst will then connect to the IMP process inside the container.

Warning

To set this property makes only sense as long you have a firewall in place, which prevents external attackers to connect to the host ports, and you have no other choice. Usually Bifröst can connect via the container networks to IMP directly (see networks).

This is usually required, if you run Bifröst on a Docker/Podman for Desktop installation (such as on Windows or macOS) where the Docker daemon does not run on the host directly, but inside virtual machine.

cleanOrphan

bool Container = true

While the housekeeping iterations this environment will look for containers that can be inspected by its docker daemon connection if there is any container that does not belong to any flow of this Bifröst instance.

This is useful to clean up old containers which are leftovers after you changed the configuration of Bifröst.

Warning

If there are using multiple Bifröst installations the same Docker host, this should be disabled. Otherwise, each instance is removing the container of the other instance.

Preparation Processes

If events about preparation processes are emitted by this environment, they are picked up by connections (like SSH) and handled.

The docker environment emits the following processes:

pull-image

In cases if an image needs to be pulled, either it does not exist or imagePullPolicy is to always, the image pull process starts. As this will block the user interaction with its session, this process event is emitted. It makes it possible to show the progress of download to the user.

Properties

image

string

Holds the tag of the image to be downloaded.

Examples

  1. Simple:
    1
    type: docker
    
  2. With ubuntu image:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    type: docker
    image: ubuntu
    ## Using /bin/bash instead of /bin/sh,
    ## because it does exist in the image
    shellCommand: [/bin/bash]
    execCommand: [/bin/bash, -c]
    
    ## Only allow login if the OIDC's groups has "my-great-group-uuid"
    ## ...and the tid (tenant ID) is "my-great-tenant-uuid"
    loginAllowed: |
        {{ and
          (.authorization.idToken.groups | has "my-great-group-uuid")
          (.authorization.idToken.tid    | eq  "my-great-tenant-uuid")
        }}
    
  3. Using my own registry with secret from file:
    1
    2
    3
    4
    5
    type: docker
    image: my.own.registry.com/foo/bar
    ## Using the pull credentials, which are stored inside:
    ## /etc/engity/bifroest/secrets/my.own.registry.com
    imagePullCredentials: "{{ file `/etc/engity/bifroest/secrets/my.own.registry.com` }}"
    
  4. Using my own registry with secret from environment variable:
    1
    2
    3
    4
    5
    type: docker
    image: my.own.registry.com/foo/bar
    ## Using the pull credentials, which are stored inside
    ## MY_GREAT_SECRET environment variable
    imagePullCredentials: "{{ env `MY_GREAT_SECRET` }}"
    

Compatibility

linux windows
/ /