Local environment
A local environment is executed on the host itself (same host on which Bifröst is running).
Currently, we support different variants provided by the host operating system which is executing the environment.
Type identifier is local
.
Linux
The Linux variant is only supported by Linux based operating systems.
It can run as the Bifröst user itself, but can also impersonate another user.
Note
If impersonating another user Bifröst is running at, root permissions are required.
User requirement
Users have to fulfill the defined requirements (name
, displayName
, uid
, group
, groups
, shell
, homeDir
and skel
).
If a user does not fulfill this requirement they are not eligible for the environment. The environment can creates a user (createIfAbsent
= true
) or even updates an existing one (updateIfDifferent
= true
) to match this requirement. This does not make a lot of sense for local users; but for users authorized via OIDC - which usually do not exist locally.
See the evaluation matrix of createIfAbsent
and updateIfDifferent
to see the actual reactions of the local environment per users requirement evaluation state.
Configuration
type
Environment Type = "local"
Has to be set to local
to enable the local environment.
loginAllowed
bool Authorization = true
Has to be true (after being evaluated) that the user is allowed to use this environment.
Examples
-
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"}}`) }}
-
Require that the user authorized via OIDC has in the group
my-great-group-uuid
and the tenant ID (tid
) in this OIDC ID token:1 2 3 4 5
loginAllowed: | {{ and (.authorization.idToken.groups | has "my-great-group-uuid") (.authorization.idToken.tid | eq "my-great-tenant-uuid") }}
name
string Authorization
The username the user should have. Empty means this requirement won't be evaluated or applied (in case of creation/modification of a user).
Examples
- Use the name of the local user:
1
name: "{{.authorization.user.name}}"
- Use the email address of the user authorized via OIDC:
1
name: "{{.authorization.idToken.email}}"
- Always use
foobar
:1
name: "foobar"
displayName
string Authorization
The display name (or title or GECOS) the user should have.
Examples
- In case of local user should be never be defined.
- Use the e-mail address of the user authorized via OIDC:
1
displayName: "{{.authorization.idToken.name}}"
- Always use
Foobar
:1
displayName: "Foobar"
uid
uint32 Authorization
The UID (user identifier) the user should have. Empty means this requirement won't be evaluated or applied (in case of creation/modification of a user).
Examples
- Use the name of the local user:
1
uid: "{{.authorization.user.uid}}"
- In case of users authorized via OIDC this should usually not be defined.
- Always use
123
:1
uid: 123
group
The primary group the user should have. Empty means this requirement won't be evaluated or applied (in case of creation/modification of a user).
Examples
- If local user is used, this should usually not be defined.
- Assign always group with name
oidc
in case of users authorized via OIDC:1 2
group: name: "oidc"
groups
[]Group
The groups (do not confuse with the primary group) the user should have. Empty means this requirement won't be evaluated or applied (in case of creation/modification of a user).
Examples
- If local user is used, this should usually not be defined.
- Assign always group with name
oidc
in case of users authorized via OIDC:1 2
groups: - name: "oidc"
shell
File Path Authorization = "/bin/sh"
The shell the user should have. Not defined means this requirement won't be evaluated or applied (in case of creation/modification of a user).
homeDir
File Path Authorization = "/home/<user.name>"
The home directory the user should have. Not defined means this requirement won't be evaluated or applied (in case of creation/modification of a user).
skel
File Path Authorization = "/etc/skel"
If a new user needs to be created in a directory on the Bifröst hosts, it will receive its initial files of its home directory from (= user's home skeleton/template directory).
createIfAbsent
string Authorization = false
Will create the local user if it does not exist to match the provided requirements (see below). If this property is false
the user has to exist, otherwise the execution will fail and the connection will be closed immediately.
This property (together with updateIfDifferent
) has to be true
if you're using authorizations like OIDC, where the user is not expected to exist locally, and you don't want to create each user individually.
Evaluation
createIfAbsent |
= false |
= true |
---|---|---|
Exists and matches | Accepted | Accepted |
Exists, but does not match | Does not apply | Does not apply |
Does not exist | Rejected | Created and accepted |
updateIfDifferent
bool Authorization = false
If an existing user does not match the provided requirements (see below) and the property is true
, this user is asked to match the requirements.
This property (together with createIfAbsent
) should be true
if you're using authorizations like OIDC, where the user is not expected to exist locally and you don't want to create each user individually.
Evaluation
updateIfDifferent |
= false |
= true |
---|---|---|
Exists and matches | Accepted | Accepted |
Exists but does not match | Rejected | Modified and accepted |
Does not exist | Does not apply | Does not apply |
banner
string Authorization = ""
Will be displayed to the user upon connection to its environment.
Examples
- If local user is used, show its name in a message:
1
banner: "Hello, {{.authorization.user.name}}!\n"
- 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.
dispose
Defines what happens if an environment is disposed.
Examples
- Use existing UNIX user:
1 2
type: local name: "{{.authorization.user.name}}"
- OIDC - create/modify user if absent/different and cleanup automatically:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
type: local ## Ensure users get created/modified if absent/different... createIfAbsent: true updateIfDifferent: true ## Use the email address of the OIDC's ID token name: "{{.authorization.idToken.email}}" ## Use the display name of the OIDC's ID token displayName: "{{.authorization.idToken.name}}" groups: ## Ensure user has always the group `oidc` assigned for better access control ## on the host itself. - name: oidc shell: "/bin/bash" ## 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") }}
Group
name
string Authorization
The name the group should have. Empty means this requirement won't be evaluated or applied (in case of creation/modification of a user).
Examples
- In case of local user this should usually not be used.
- Use the email address of the user authorized via OIDC always set the name
oidc
:1
name: "oidc"
gid
uint32 Authorization
The GID (group identifier) the group should have. Empty means this requirement won't be evaluated or applied (in case of creation/modification of a user).
Examples
- Always use
123
1
gid: 123
Dispose
Defines the behavior of an environment on disposal (cleanup).
deleteManagedUser
bool Authorization = true
If true
the environment will also delete users, created/managed by it. Usually, if createIfAbsent
and updateIfDifferent
is both false
this has no effect.
deleteManagedUserHomeDir
bool Authorization = true
In combination with deleteManagedUser
, if true
the environment will also delete the user's home directory.
killManagedUserProcesses
bool Authorization = true
In combination with deleteManagedUser
, if true
the environment will also kill all user's running processes.
Windows
The Windows variant is only supported by Windows 7+ based operating systems.
Warning
In contrast to the Linux version this variant CANNOT impersonate. As a consequence, each user session always executes as the user the Bifröst process itself runs with.
Impersonating on a Windows machine requires either full credentials (password) or another running process the session tokens can be cloned from. As both conflicts how we intend Bifröst to work, both solutions leave a lot of use-cases behind. Since it is very "hacky", we decided to stick with the simple approach.
Configuration
type
Environment Type = "local"
Has to be set to local
to enable the local environment.
loginAllowed
bool Authorization = true
Has to be true (after being evaluated) that the user is allowed to use this environment.
Examples
- Require that the user authorized via OIDC has in the group
my-great-group-uuid
and the tenant ID (tid
) in this OIDC ID token:1 2 3 4 5
loginAllowed: | {{ and (.authorization.idToken.groups | has "my-great-group-uuid") (.authorization.idToken.tid | eq "my-great-tenant-uuid") }}
banner
string Authorization
Will be displayed to the user upon connection to its environment.
Examples
- If users authorized via OIDC is used, show its name in a message:
1
banner: "Hello, {{.authorization.idToken.name}}!\n"
shellCommand
string Authorization =
["C:\\WINDOWS\\system32\\cmd.exe"]
The shell which is used to execute the user's session.
execCommandPrefix
string Authorization =
["C:\\WINDOWS\\system32\\cmd.exe", "/C"]
The executor command prefix which is used when a user executes a command instead of executing into a shell.
If the user will execute ssh foo@bar.com echo "bar"
on the host C:\WINDOWS\system32\cmd.exe /C 'echo "bar"'
will be executed.
directory
"<working directory of Bifröst>"
The working directory in which the command will be executed in.
portForwardingAllowed
bool Authorization = true
If true
, users are allowed to use SSH's port forwarding mechanism.
Examples
- Simple:
1
type: local
- OIDC:
1 2 3 4 5 6 7 8 9 10 11 12 13
type: local ## Use the PowerShell Core without banner as Shell shellCommand: ["pwsh.exe", "-NoLogo"] directory: "C:\\my\\home" ## 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") }}
`## Compatibility
linux |
windows |
---|---|
/ | / |
` |