-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #195 from jkl73/launchpolicy
Launcher: Add launch policy for cmd and env vars
- Loading branch information
Showing
7 changed files
with
239 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package spec | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
// LaunchPolicy contains policies on starting the container. | ||
// The policy comes from the labels of the image. | ||
type LaunchPolicy struct { | ||
AllowedEnvOverride []string | ||
AllowedCmdOverride bool | ||
} | ||
|
||
const ( | ||
envOverride = "tee.launch_policy.allow_env_override" | ||
cmdOverride = "tee.launch_policy.allow_cmd_override" | ||
) | ||
|
||
// GetLaunchPolicy takes in a map[string] string which should come from image labels, | ||
// and will try to parse it into a LaunchPolicy. Extra fields will be ignored. | ||
func GetLaunchPolicy(imageLabels map[string]string) (LaunchPolicy, error) { | ||
var err error | ||
launchPolicy := LaunchPolicy{} | ||
if v, ok := imageLabels[envOverride]; ok { | ||
envs := strings.Split(v, ",") | ||
for _, env := range envs { | ||
// strip out empty env name | ||
if env != "" { | ||
launchPolicy.AllowedEnvOverride = append(launchPolicy.AllowedEnvOverride, env) | ||
} | ||
} | ||
} | ||
|
||
if v, ok := imageLabels[cmdOverride]; ok { | ||
if launchPolicy.AllowedCmdOverride, err = strconv.ParseBool(v); err != nil { | ||
return LaunchPolicy{}, fmt.Errorf("value of LABEL %s of the image is not a boolean %s", cmdOverride, v) | ||
} | ||
} | ||
|
||
return launchPolicy, nil | ||
} | ||
|
||
// Verify will use the LaunchPolicy to verify the given LauncherSpec. If the verification passed, will return nil. | ||
// If there are multiple violations, the function will return the first error. | ||
func (p LaunchPolicy) Verify(ls LauncherSpec) error { | ||
for _, e := range ls.Envs { | ||
if !contains(p.AllowedEnvOverride, e.Name) { | ||
return fmt.Errorf("env var %s is not allowed to be overridden on this image; allowed envs to be overridden: %v", e, p.AllowedEnvOverride) | ||
} | ||
} | ||
if !p.AllowedCmdOverride && len(ls.Cmd) > 0 { | ||
return fmt.Errorf("CMD is not allowed to be overridden on this image") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func contains(strs []string, target string) bool { | ||
for _, s := range strs { | ||
if s == target { | ||
return true | ||
} | ||
} | ||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package spec | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
) | ||
|
||
func TestLaunchPolicy(t *testing.T) { | ||
testCases := []struct { | ||
testName string | ||
imageLables map[string]string | ||
expectedPolicy LaunchPolicy | ||
}{ | ||
{ | ||
"single ENV override, CMD override", | ||
map[string]string{ | ||
envOverride: "foo", | ||
cmdOverride: "true", | ||
}, | ||
LaunchPolicy{ | ||
AllowedEnvOverride: []string{"foo"}, | ||
AllowedCmdOverride: true, | ||
}, | ||
}, | ||
{ | ||
"multiple ENV override, no CMD override", | ||
map[string]string{ | ||
envOverride: "foo,bar", | ||
}, | ||
LaunchPolicy{ | ||
AllowedEnvOverride: []string{"foo", "bar"}, | ||
AllowedCmdOverride: false, | ||
}, | ||
}, | ||
{ | ||
"no ENV override, no CMD override", | ||
nil, | ||
LaunchPolicy{ | ||
AllowedEnvOverride: nil, | ||
AllowedCmdOverride: false, | ||
}, | ||
}, | ||
{ | ||
"empty string in ENV override", | ||
map[string]string{ | ||
envOverride: ",,,foo", | ||
cmdOverride: "false", | ||
}, | ||
LaunchPolicy{ | ||
AllowedEnvOverride: []string{"foo"}, | ||
AllowedCmdOverride: false, | ||
}, | ||
}, | ||
} | ||
|
||
for _, testcase := range testCases { | ||
t.Run(testcase.testName, func(t *testing.T) { | ||
got, err := GetLaunchPolicy(testcase.imageLables) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if !cmp.Equal(got, testcase.expectedPolicy) { | ||
t.Errorf("Launchspec got %+v, want %+v", got, testcase.expectedPolicy) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestVerify(t *testing.T) { | ||
testCases := []struct { | ||
testName string | ||
policy LaunchPolicy | ||
spec LauncherSpec | ||
expectErr bool | ||
}{ | ||
{ | ||
"allow everything", | ||
LaunchPolicy{ | ||
AllowedEnvOverride: []string{"foo"}, | ||
AllowedCmdOverride: true, | ||
}, | ||
LauncherSpec{ | ||
Envs: []EnvVar{{Name: "foo", Value: "foo"}}, | ||
Cmd: []string{"foo"}, | ||
}, | ||
false, | ||
}, | ||
{ | ||
"default case", | ||
LaunchPolicy{}, | ||
LauncherSpec{}, | ||
false, | ||
}, | ||
{ | ||
"env override violation", | ||
LaunchPolicy{ | ||
AllowedEnvOverride: []string{"foo"}, | ||
}, | ||
LauncherSpec{ | ||
Envs: []EnvVar{{Name: "bar", Value: ""}}, | ||
}, | ||
true, | ||
}, | ||
{ | ||
"cmd violation", | ||
LaunchPolicy{ | ||
AllowedCmdOverride: false, | ||
}, | ||
LauncherSpec{ | ||
Cmd: []string{"foo"}, | ||
}, | ||
true, | ||
}, | ||
{ | ||
"allow everything", | ||
LaunchPolicy{ | ||
AllowedEnvOverride: []string{"foo"}, | ||
AllowedCmdOverride: true, | ||
}, | ||
LauncherSpec{ | ||
Envs: []EnvVar{{Name: "foo", Value: "foo"}}, | ||
Cmd: []string{"foo"}, | ||
}, | ||
false, | ||
}, | ||
} | ||
for _, testCase := range testCases { | ||
t.Run(testCase.testName, func(t *testing.T) { | ||
err := testCase.policy.Verify(testCase.spec) | ||
if testCase.expectErr { | ||
if err == nil { | ||
t.Errorf("expected error, but got nil") | ||
} | ||
} else { | ||
if err != nil { | ||
t.Errorf("expected no error, but got %v", err) | ||
} | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters