Skip to content

Commit

Permalink
Working directory enforcement (#1305)
Browse files Browse the repository at this point in the history
* Add current working directory enforcement.

The working directory can be set as part of container image
by WORKINGDIR Dockerfile directive or could be explicitly
set inside CRI container config. Changing the CWD of container
can change the expected behavior of a container.

If the working_dir config is not present or empty inside the
policy config, this information will be gathered from container
image spec.

Add logic to enforce CWD enforcement inside GCS and extend
policy dev tool and policy structure to support this scenario.
The enforcement is an exact string match between what's in the
policy and what's in the generated container spec. If the paths
don't match, the container will fail to start.

* Minor refactor of securitypolicy_test

Add a utility funcion that picks a random container from an array
and generates a valid/invalid overlay for that container. Refactor
tests to use the new utility function.

* Add unit tests for enforcing working directory

Signed-off-by: Maksim An <maksiman@microsoft.com>
  • Loading branch information
anmaxvl authored Mar 7, 2022
1 parent 3c1a37f commit f50f975
Show file tree
Hide file tree
Showing 8 changed files with 301 additions and 172 deletions.
7 changes: 6 additions & 1 deletion internal/guest/runtime/hcsv2/uvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,12 @@ func (h *Host) CreateContainer(ctx context.Context, id string, settings *prot.VM
return nil, gcserr.NewHresultError(gcserr.HrVmcomputeSystemAlreadyExists)
}

err = h.securityPolicyEnforcer.EnforceCreateContainerPolicy(id, settings.OCISpecification.Process.Args, settings.OCISpecification.Process.Env)
err = h.securityPolicyEnforcer.EnforceCreateContainerPolicy(
id,
settings.OCISpecification.Process.Args,
settings.OCISpecification.Process.Env,
settings.OCISpecification.Process.Cwd,
)

if err != nil {
return nil, errors.Wrapf(err, "container creation denied due to policy")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ func (p *MountMonitoringSecurityPolicyEnforcer) EnforceOverlayMountPolicy(contai
return nil
}

func (p *MountMonitoringSecurityPolicyEnforcer) EnforceCreateContainerPolicy(containerID string, argList []string, envList []string) (err error) {
func (p *MountMonitoringSecurityPolicyEnforcer) EnforceCreateContainerPolicy(_ string, _ []string, _ []string, _ string) (err error) {
return nil
}
10 changes: 9 additions & 1 deletion internal/tools/securitypolicy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ func createPolicyFromConfig(config *securitypolicy.PolicyConfig) (*securitypolic
[]string{"/pause"},
[]securitypolicy.EnvRule{},
securitypolicy.AuthConfig{},
"",
)
config.Containers = append(config.Containers, pause)

Expand Down Expand Up @@ -147,7 +148,14 @@ func createPolicyFromConfig(config *securitypolicy.PolicyConfig) (*securitypolic
}
envRules = append(envRules, rule)

container, err := securitypolicy.NewContainer(containerConfig.Command, layerHashes, envRules)
workingDir := "/"
if imgConfig.Config.WorkingDir != "" {
workingDir = imgConfig.Config.WorkingDir
}
if containerConfig.WorkingDir != "" {
workingDir = containerConfig.WorkingDir
}
container, err := securitypolicy.NewContainer(containerConfig.Command, layerHashes, envRules, workingDir)
if err != nil {
return nil, err
}
Expand Down
45 changes: 29 additions & 16 deletions pkg/securitypolicy/securitypolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,27 @@ type EnvRuleConfig struct {
// ContainerConfig contains toml or JSON config for container described
// in security policy.
type ContainerConfig struct {
ImageName string `json:"image_name" toml:"image_name"`
Command []string `json:"command" toml:"command"`
Auth AuthConfig `json:"auth" toml:"auth"`
EnvRules []EnvRule `json:"env_rules" toml:"env_rule"`
ImageName string `json:"image_name" toml:"image_name"`
Command []string `json:"command" toml:"command"`
Auth AuthConfig `json:"auth" toml:"auth"`
EnvRules []EnvRule `json:"env_rules" toml:"env_rule"`
WorkingDir string `json:"working_dir" toml:"working_dir"`
}

// NewContainerConfig creates a new ContainerConfig from the given values.
func NewContainerConfig(imageName string, command []string, envRules []EnvRule, auth AuthConfig) ContainerConfig {
func NewContainerConfig(
imageName string,
command []string,
envRules []EnvRule,
auth AuthConfig,
workingDir string,
) ContainerConfig {
return ContainerConfig{
ImageName: imageName,
Command: command,
EnvRules: envRules,
Auth: auth,
ImageName: imageName,
Command: command,
EnvRules: envRules,
Auth: auth,
WorkingDir: workingDir,
}
}

Expand All @@ -72,6 +80,9 @@ type securityPolicyContainer struct {
// order that the layers are overlayed is important and needs to be enforced
// as part of policy.
Layers []string `json:"layers"`
// WorkingDir is a path to container's working directory, which all the processes
// will default to.
WorkingDir string `json:"working_dir"`
}

// SecurityPolicyState is a structure that holds user supplied policy to enforce
Expand Down Expand Up @@ -141,9 +152,10 @@ type Containers struct {
}

type Container struct {
Command CommandArgs `json:"command"`
EnvRules EnvRules `json:"env_rules"`
Layers Layers `json:"layers"`
Command CommandArgs `json:"command"`
EnvRules EnvRules `json:"env_rules"`
Layers Layers `json:"layers"`
WorkingDir string `json:"working_dir"`
}

type Layers struct {
Expand All @@ -170,14 +182,15 @@ type EnvRule struct {

// NewContainer creates a new Container instance from the provided values
// or an error if envRules validation fails.
func NewContainer(command, layers []string, envRules []EnvRule) (*Container, error) {
func NewContainer(command, layers []string, envRules []EnvRule, workingDir string) (*Container, error) {
if err := validateEnvRules(envRules); err != nil {
return nil, err
}
return &Container{
Command: newCommandArgs(command),
Layers: newLayers(layers),
EnvRules: newEnvRules(envRules),
Command: newCommandArgs(command),
Layers: newLayers(layers),
EnvRules: newEnvRules(envRules),
WorkingDir: workingDir,
}, nil
}

Expand Down
Loading

0 comments on commit f50f975

Please sign in to comment.