Skip to content

Commit

Permalink
Refactor environment.
Browse files Browse the repository at this point in the history
Signed-off-by: Matthias Glastra <[email protected]>
  • Loading branch information
matglas committed Oct 14, 2024
1 parent ecacd4e commit d714a76
Show file tree
Hide file tree
Showing 10 changed files with 449 additions and 352 deletions.
2 changes: 1 addition & 1 deletion attestation/commandrun/commandrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"os/exec"

"github.com/in-toto/go-witness/attestation"
"github.com/in-toto/go-witness/attestation/environment"
"github.com/in-toto/go-witness/environment"
"github.com/in-toto/go-witness/cryptoutil"
"github.com/invopop/jsonschema"
)
Expand Down
4 changes: 4 additions & 0 deletions attestation/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/gobwas/glob"
"github.com/in-toto/go-witness/cryptoutil"
"github.com/in-toto/go-witness/environment"
"github.com/in-toto/go-witness/log"
)

Expand Down Expand Up @@ -117,6 +118,7 @@ type AttestationContext struct {
materials map[string]cryptoutil.DigestSet
stepName string
mutex sync.RWMutex
environmentCapturer *environment.Capture
}

type Product struct {
Expand Down Expand Up @@ -229,6 +231,8 @@ func (ctx *AttestationContext) DirHashGlob() []glob.Glob {
return ctx.dirHashGlobCompiled
}



func (ctx *AttestationContext) CompletedAttestors() []CompletedAttestor {
ctx.mutex.RLock()
out := make([]CompletedAttestor, len(ctx.completedAttestors))
Expand Down
52 changes: 52 additions & 0 deletions attestation/context_env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2024 The Witness Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package attestation

import (
env "github.com/in-toto/go-witness/environment"
)

func (ctx *AttestationContext) EnvironmentCapturer() *env.Capture {
return ctx.environmentCapturer
}

// WithEnvFilterVarsEnabled will make the filter (removing) of vars the acting behavior.
// The default behavior is obfuscation of variables.
func WithEnvFilterVarsEnabled() AttestationContextOption {
return func(a *AttestationContext) {
env.WithFilterVarsEnabled()(a.environmentCapturer)
}
}

// WithEnvAdditionalKeys add additional keys to final list that is checked for sensitive variables.
func WithEnvAdditionalKeys(additionalKeys []string) AttestationContextOption {
return func(a *AttestationContext) {
env.WithAdditionalKeys(additionalKeys)(a.environmentCapturer)
}
}

// WithEnvExcludeKeys add additional keys to final list that is checked for sensitive variables.
func WithEnvExcludeKeys(excludeKeys []string) AttestationContextOption {
return func(a *AttestationContext) {
env.WithExcludeKeys(excludeKeys)(a.environmentCapturer)
}
}

// WithEnvDisableDefaultSensitiveList will disable the default list and only use the additional keys.
func WithEnvDisableDefaultSensitiveList() AttestationContextOption {
return func(a *AttestationContext) {
env.WithDisableDefaultSensitiveList()(a.environmentCapturer)
}
}
198 changes: 61 additions & 137 deletions attestation/environment/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,11 @@
package environment

import (
"fmt"
"os"
"os/user"
"runtime"
"strings"

"github.com/in-toto/go-witness/attestation"
"github.com/in-toto/go-witness/registry"
"github.com/invopop/jsonschema"
)

Expand Down Expand Up @@ -51,64 +48,64 @@ type EnvironmentAttestor interface {
}

func init() {
attestation.RegisterAttestation(Name, Type, RunType, func() attestation.Attestor { return New() },
registry.BoolConfigOption(
"filter-sensitive-vars",
"Switch from obfuscate to filtering variables which removes them from the output completely.",
defaultFilterSensitiveVarsEnabled,
func(a attestation.Attestor, filterSensitiveVarsEnabled bool) (attestation.Attestor, error) {
envAttestor, ok := a.(*Attestor)
if !ok {
return a, fmt.Errorf("unexpected attestor type: %T is not a environment attestor", a)
}

WithFilterVarsEnabled()(envAttestor)
return envAttestor, nil
},
),
registry.BoolConfigOption(
"disable-default-sensitive-vars",
"Disable the default list of sensitive vars and only use the items mentioned by --attestor-environment-sensitive-key.",
defaultDisableSensitiveVarsDefault,
func(a attestation.Attestor, disableSensitiveVarsDefault bool) (attestation.Attestor, error) {
envAttestor, ok := a.(*Attestor)
if !ok {
return a, fmt.Errorf("unexpected attestor type: %T is not a environment attestor", a)
}

WithDisableDefaultSensitiveList()(envAttestor)
return envAttestor, nil
},
),
registry.StringSliceConfigOption(
"add-sensitive-key",
"Add keys or globs (e.g. '*TEXT') to the list of sensitive environment keys.",
[]string{},
func(a attestation.Attestor, additionalKeys []string) (attestation.Attestor, error) {
envAttestor, ok := a.(*Attestor)
if !ok {
return a, fmt.Errorf("unexpected attestor type: %T is not a environment attestor", a)
}

WithAdditionalKeys(additionalKeys)(envAttestor)
return envAttestor, nil
},
),
registry.StringSliceConfigOption(
"exclude-sensitive-key",
"Exclude specific keys from the list of sensitive environment keys. Note: This does not support globs.",
[]string{},
func(a attestation.Attestor, excludeKeys []string) (attestation.Attestor, error) {
envAttestor, ok := a.(*Attestor)
if !ok {
return a, fmt.Errorf("unexpected attestor type: %T is not a environment attestor", a)
}

WithExcludeKeys(excludeKeys)(envAttestor)
return envAttestor, nil
},
),
)
// attestation.RegisterAttestation(Name, Type, RunType, func() attestation.Attestor { return New() },
// registry.BoolConfigOption(
// "filter-sensitive-vars",
// "Switch from obfuscate to filtering variables which removes them from the output completely.",
// defaultFilterSensitiveVarsEnabled,
// func(a attestation.Attestor, filterSensitiveVarsEnabled bool) (attestation.Attestor, error) {
// envAttestor, ok := a.(*Attestor)
// if !ok {
// return a, fmt.Errorf("unexpected attestor type: %T is not a environment attestor", a)
// }

// envCapture.WithFilterVarsEnabled()(envAttestor.capture)
// return envAttestor, nil
// },
// ),
// registry.BoolConfigOption(
// "disable-default-sensitive-vars",
// "Disable the default list of sensitive vars and only use the items mentioned by --attestor-environment-sensitive-key.",
// defaultDisableSensitiveVarsDefault,
// func(a attestation.Attestor, disableSensitiveVarsDefault bool) (attestation.Attestor, error) {
// envAttestor, ok := a.(*Attestor)
// if !ok {
// return a, fmt.Errorf("unexpected attestor type: %T is not a environment attestor", a)
// }

// envCapture.WithDisableDefaultSensitiveList()(envAttestor.capture)
// return envAttestor, nil
// },
// ),
// registry.StringSliceConfigOption(
// "add-sensitive-key",
// "Add keys or globs (e.g. '*TEXT') to the list of sensitive environment keys.",
// []string{},
// func(a attestation.Attestor, additionalKeys []string) (attestation.Attestor, error) {
// envAttestor, ok := a.(*Attestor)
// if !ok {
// return a, fmt.Errorf("unexpected attestor type: %T is not a environment attestor", a)
// }

// envCapture.WithAdditionalKeys(additionalKeys)(envAttestor.capture)
// return envAttestor, nil
// },
// ),
// registry.StringSliceConfigOption(
// "exclude-sensitive-key",
// "Exclude specific keys from the list of sensitive environment keys. Note: This does not support globs.",
// []string{},
// func(a attestation.Attestor, excludeKeys []string) (attestation.Attestor, error) {
// envAttestor, ok := a.(*Attestor)
// if !ok {
// return a, fmt.Errorf("unexpected attestor type: %T is not a environment attestor", a)
// }

// envCapture.WithExcludeKeys(excludeKeys)(envAttestor.capture)
// return envAttestor, nil
// },
// ),
// )
}

type Attestor struct {
Expand All @@ -117,49 +114,11 @@ type Attestor struct {
Username string `json:"username"`
Variables map[string]string `json:"variables,omitempty"`

osEnviron func() []string
sensitiveVarsList map[string]struct{}
addSensitiveVarsList map[string]struct{}
excludeSensitiveVarsList map[string]struct{}
filterVarsEnabled bool
disableSensitiveVarsDefault bool
osEnviron func() []string
}

type Option func(*Attestor)

// WithFilterVarsEnabled will make the filter (removing) of vars the acting behavior.
// The default behavior is obfuscation of variables.
func WithFilterVarsEnabled() Option {
return func(a *Attestor) {
a.filterVarsEnabled = true
}
}

// WithAdditionalKeys add additional keys to final list that is checked for sensitive variables.
func WithAdditionalKeys(additionalKeys []string) Option {
return func(a *Attestor) {
for _, value := range additionalKeys {
a.addSensitiveVarsList[value] = struct{}{}
}
}
}

// WithExcludeKeys add additional keys to final list that is checked for sensitive variables.
func WithExcludeKeys(excludeKeys []string) Option {
return func(a *Attestor) {
for _, value := range excludeKeys {
a.excludeSensitiveVarsList[value] = struct{}{}
}
}
}

// WithDisableDefaultSensitiveList will disable the default list and only use the additional keys.
func WithDisableDefaultSensitiveList() Option {
return func(a *Attestor) {
a.disableSensitiveVarsDefault = true
}
}

// WithCustomEnv will override the default os.Environ() method. This could be used to mock.
func WithCustomEnv(osEnviron func() []string) Option {
return func(a *Attestor) {
Expand All @@ -168,11 +127,7 @@ func WithCustomEnv(osEnviron func() []string) Option {
}

func New(opts ...Option) *Attestor {
attestor := &Attestor{
sensitiveVarsList: DefaultSensitiveEnvList(),
addSensitiveVarsList: map[string]struct{}{},
excludeSensitiveVarsList: map[string]struct{}{},
}
attestor := &Attestor{}

attestor.osEnviron = os.Environ

Expand Down Expand Up @@ -211,42 +166,11 @@ func (a *Attestor) Attest(ctx *attestation.AttestationContext) error {
a.Username = user.Username
}

// Prepare sensitive keys list.
var finalSensitiveKeysList map[string]struct{}
if a.disableSensitiveVarsDefault {
a.sensitiveVarsList = map[string]struct{}{}
}
finalSensitiveKeysList = a.sensitiveVarsList
for k, v := range a.addSensitiveVarsList {
finalSensitiveKeysList[k] = v
}

// Filter or obfuscate
if a.filterVarsEnabled {
FilterEnvironmentArray(a.osEnviron(), finalSensitiveKeysList, a.excludeSensitiveVarsList, func(key, val, _ string) {
a.Variables[key] = val
})
} else {
ObfuscateEnvironmentArray(a.osEnviron(), finalSensitiveKeysList, a.excludeSensitiveVarsList, func(key, val, _ string) {
a.Variables[key] = val
})
}
a.Variables = ctx.EnvironmentCapturer().Capture(a.osEnviron())

return nil
}

func (a *Attestor) Data() *Attestor {
return a
}

// splitVariable splits a string representing an environment variable in the format of
// "KEY=VAL" and returns the key and val separately.
func splitVariable(v string) (key, val string) {
parts := strings.SplitN(v, "=", 2)
key = parts[0]
if len(parts) > 1 {
val = parts[1]
}

return
}
Loading

0 comments on commit d714a76

Please sign in to comment.