Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

documentation update and minor code fixes #1137

Merged
merged 4 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions app/sentinel/internal/cli/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import (
"github.com/vmware-tanzu/secrets-manager/core/constants/sentinel"
)

// ParseList adds a flag to the parser for listing all registered workloads.
// It returns a pointer to a boolean that will be set to true if the flag is
// used.
func ParseList(parser *argparse.Parser) *bool {
return parser.Flag(
string(sentinel.List),
Expand All @@ -24,6 +27,10 @@ func ParseList(parser *argparse.Parser) *bool {
})
}

// ParseDeleteSecret adds a flag to the parser for deleting a secret associated
// with a workload.
// It returns a pointer to a boolean that will be set to true if the flag is
// used.
func ParseDeleteSecret(parser *argparse.Parser) *bool {
return parser.Flag(
string(sentinel.Remove),
Expand All @@ -33,6 +40,10 @@ func ParseDeleteSecret(parser *argparse.Parser) *bool {
})
}

// ParseAppendSecret adds a flag to the parser for appending a secret to an
// existing secret collection.
// It returns a pointer to a boolean that will be set to true if the flag is
// used.
func ParseAppendSecret(parser *argparse.Parser) *bool {
return parser.Flag(
string(sentinel.Join),
Expand All @@ -43,6 +54,10 @@ func ParseAppendSecret(parser *argparse.Parser) *bool {
})
}

// ParseNamespaces adds a string list argument to the parser for specifying
// namespaces.
// It returns a pointer to a slice of strings containing the specified
// namespaces.
func ParseNamespaces(parser *argparse.Parser) *[]string {
return parser.StringList(
string(sentinel.Namespace),
Expand All @@ -52,6 +67,8 @@ func ParseNamespaces(parser *argparse.Parser) *[]string {
})
}

// ParseInputKeys adds a string argument to the parser for inputting keys.
// It returns a pointer to a string containing the input keys.
func ParseInputKeys(parser *argparse.Parser) *string {
return parser.String(
string(sentinel.Keys),
Expand All @@ -62,6 +79,9 @@ func ParseInputKeys(parser *argparse.Parser) *string {
})
}

// ParseWorkload adds a string list argument to the parser for specifying
// workload names.
// It returns a pointer to a slice of strings containing the workload names.
func ParseWorkload(parser *argparse.Parser) *[]string {
return parser.StringList(
string(sentinel.Workload),
Expand All @@ -71,6 +91,8 @@ func ParseWorkload(parser *argparse.Parser) *[]string {
})
}

// ParseSecret adds a string argument to the parser for specifying a secret.
// It returns a pointer to a string containing the secret.
func ParseSecret(parser *argparse.Parser) *string {
return parser.String(
string(sentinel.Secret),
Expand All @@ -80,6 +102,9 @@ func ParseSecret(parser *argparse.Parser) *string {
})
}

// ParseTemplate adds a string argument to the parser for specifying a
// transformation template.
// It returns a pointer to a string containing the template.
func ParseTemplate(parser *argparse.Parser) *string {
return parser.String(
string(sentinel.Transformation),
Expand All @@ -89,6 +114,9 @@ func ParseTemplate(parser *argparse.Parser) *string {
})
}

// ParseFormat adds a string argument to the parser for specifying the output
// format.
// It returns a pointer to a string containing the format.
func ParseFormat(parser *argparse.Parser) *string {
return parser.String(
string(sentinel.Format),
Expand All @@ -100,6 +128,9 @@ func ParseFormat(parser *argparse.Parser) *string {
})
}

// ParseEncrypt adds a flag to the parser for encrypting or decrypting secrets.
// It returns a pointer to a boolean that will be set to true if the flag is
// used.
func ParseEncrypt(parser *argparse.Parser) *bool {
return parser.Flag(
string(sentinel.Encrypt),
Expand All @@ -111,6 +142,9 @@ func ParseEncrypt(parser *argparse.Parser) *bool {
})
}

// ParseExpires adds a string argument to the parser for specifying the
// expiration date of a secret.
// It returns a pointer to a string containing the expiration date.
func ParseExpires(parser *argparse.Parser) *string {
return parser.String(
string(sentinel.Expires),
Expand All @@ -120,6 +154,9 @@ func ParseExpires(parser *argparse.Parser) *string {
})
}

// ParseNotBefore adds a string argument to the parser for specifying the
// start date of a secret's validity.
// It returns a pointer to a string containing the start date.
func ParseNotBefore(parser *argparse.Parser) *string {
return parser.String(
string(sentinel.NotBefore),
Expand Down
38 changes: 35 additions & 3 deletions app/sentinel/internal/initialization/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,64 +24,96 @@ import (
"github.com/vmware-tanzu/secrets-manager/core/spiffe"
)

// OSFileOpener is a struct that provides a method to open files.
type OSFileOpener struct{}

// Open opens the named file and returns an *os.File.
func (OSFileOpener) Open(name string) (*os.File, error) {
return os.Open(name)
}

// EnvConfigReader is a struct that provides methods to read environment
// configurations.
type EnvConfigReader struct{}

// InitCommandPathForSentinel returns the path for the sentinel
// initialization command.
func (EnvConfigReader) InitCommandPathForSentinel() string {
return env.InitCommandPathForSentinel()
}

// InitCommandRunnerWaitBeforeExecIntervalForSentinel returns the wait interval
// before executing the sentinel initialization command.
func (EnvConfigReader) InitCommandRunnerWaitBeforeExecIntervalForSentinel() time.Duration {
return env.InitCommandRunnerWaitBeforeExecIntervalForSentinel()
}

// InitCommandRunnerWaitIntervalBeforeInitComplete returns the wait interval
// before the initialization is complete.
func (EnvConfigReader) InitCommandRunnerWaitIntervalBeforeInitComplete() time.Duration {
return env.InitCommandRunnerWaitIntervalBeforeInitComplete()
}

// NamespaceForVSecMSystem returns the namespace for the VSecM system.
func (EnvConfigReader) NamespaceForVSecMSystem() string {
return env.NamespaceForVSecMSystem()
}

// StandardLogger is a struct that provides logging methods.
type StandardLogger struct{}

// InfoLn logs info level messages.
func (StandardLogger) InfoLn(correlationID *string, v ...interface{}) {
std.InfoLn(correlationID, v...)
}

// ErrorLn logs error level messages.
func (StandardLogger) ErrorLn(correlationID *string, v ...interface{}) {
std.ErrorLn(correlationID, v...)
}

// TraceLn logs trace level messages.
func (StandardLogger) TraceLn(correlationID *string, v ...interface{}) {
std.TraceLn(correlationID, v...)
}

// WarnLn logs warning level messages.
func (StandardLogger) WarnLn(correlationID *string, v ...interface{}) {
std.WarnLn(correlationID, v...)
}

// FatalLn logs fatal level messages.
func (StandardLogger) FatalLn(correlationID *string, v ...interface{}) {
std.FatalLn(correlationID, v...)
}

// SafeClient is a struct that provides methods to interact with the safe.
type SafeClient struct{}

func (SafeClient) Check(ctx context.Context, src *workloadapi.X509Source) error {
// Check performs a check operation using the provided context and X509Source.
func (SafeClient) Check(ctx context.Context,
src *workloadapi.X509Source) error {
return safe.Check(ctx, src)
}

func (SafeClient) CheckInitialization(ctx context.Context, src *workloadapi.X509Source) (bool, error) {
// CheckInitialization checks the initialization status using the provided
// context and X509Source.
func (SafeClient) CheckInitialization(ctx context.Context,
src *workloadapi.X509Source) (bool, error) {
return safe.CheckInitialization(ctx, src)
}

// Post sends a SentinelCommand to the safe using the provided context.
func (SafeClient) Post(ctx context.Context, sc data.SentinelCommand) error {
return safe.Post(ctx, sc)
}

// SpiffeClient is a struct that provides methods to interact with SPIFFE.
type SpiffeClient struct{}

func (SpiffeClient) AcquireSourceForSentinel(ctx context.Context) (*workloadapi.X509Source, bool) {
// AcquireSourceForSentinel acquires an X509Source for the sentinel using
// the provided context.
func (SpiffeClient) AcquireSourceForSentinel(
ctx context.Context) (*workloadapi.X509Source, bool) {
return spiffe.AcquireSourceForSentinel(ctx)
}
3 changes: 2 additions & 1 deletion app/sentinel/internal/initialization/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import (
"github.com/vmware-tanzu/secrets-manager/lib/backoff"
)

func (i *Initializer) commandFileScanner(cid *string) (*os.File, *bufio.Scanner) {
func (i *Initializer) commandFileScanner(
cid *string) (*os.File, *bufio.Scanner) {
filePath := i.EnvReader.InitCommandPathForSentinel()
file, err := i.FileOpener.Open(filePath)

Expand Down
21 changes: 14 additions & 7 deletions app/sentinel/internal/initialization/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,23 @@ import (
entity "github.com/vmware-tanzu/secrets-manager/core/entity/v1/data"
)

// FileOpener is an interface for the file operations that the Sentinel needs to perform.
// FileOpener is an interface for the file operations that the Sentinel
// needs to perform.
type FileOpener interface {
Open(name string) (*os.File, error)
}

// EnvReader is an interface for the environment variables that the Sentinel needs to read.
// EnvReader is an interface for the environment variables that the Sentinel
// needs to read.
type EnvReader interface {
InitCommandPathForSentinel() string
InitCommandRunnerWaitBeforeExecIntervalForSentinel() time.Duration
InitCommandRunnerWaitIntervalBeforeInitComplete() time.Duration
NamespaceForVSecMSystem() string
}

// Logger is an interface for the logging operations that the Sentinel needs to perform.
// Logger is an interface for the logging operations that the Sentinel
// needs to perform.
type Logger interface {
InfoLn(correlationID *string, v ...any)
ErrorLn(correlationID *string, v ...any)
Expand All @@ -42,16 +45,20 @@ type Logger interface {
FatalLn(correlationID *string, v ...any)
}

// SafeOps is an interface for the Safe operations that the Sentinel needs to perform.
// SafeOps is an interface for the Safe operations that the Sentinel needs
// to perform.
type SafeOps interface {
Check(ctx context.Context, src *workloadapi.X509Source) error
CheckInitialization(ctx context.Context, src *workloadapi.X509Source) (bool, error)
CheckInitialization(ctx context.Context,
src *workloadapi.X509Source) (bool, error)
Post(ctx context.Context, sc entity.SentinelCommand) error
}

// SpiffeOps is an interface for the Spiffe operations that the Sentinel needs to perform.
// SpiffeOps is an interface for the Spiffe operations that the Sentinel needs
// to perform.
type SpiffeOps interface {
AcquireSourceForSentinel(ctx context.Context) (*workloadapi.X509Source, bool)
AcquireSourceForSentinel(
ctx context.Context) (*workloadapi.X509Source, bool)
}

type Initializer struct {
Expand Down
12 changes: 8 additions & 4 deletions app/sentinel/internal/oidc/engine/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ func withLogger(logger logger) authOption {
}
}

// IsAuthorized checks if the JWT (access token) is authorized based on the OAuth 2.0 Token Introspection standard.
// IsAuthorized checks if the JWT (access token) is authorized based on the
// OAuth 2.0 Token Introspection standard.
func (a *auth) IsAuthorized(id string, r *http.Request) bool {
return a.isAuthorizedJWT(id, r)
}
Expand Down Expand Up @@ -112,7 +113,8 @@ func (a *auth) isAuthorizedJWT(cid string, r *http.Request) bool {

// Create a new HTTP request to the introspection endpoint with the required
// data.
req, err := http.NewRequest("POST", env.OIDCProviderBaseUrlForSentinel(), strings.NewReader(data.Encode()))
req, err := http.NewRequest("POST",
env.OIDCProviderBaseUrlForSentinel(), strings.NewReader(data.Encode()))
if err != nil {
a.log.ErrorLn(&cid, "isAuthorizedJWT: error creating request:", err)
return false
Expand All @@ -126,7 +128,8 @@ func (a *auth) isAuthorizedJWT(cid string, r *http.Request) bool {
}
defer func() {
if err := resp.Body.Close(); err != nil {
a.log.ErrorLn(&cid, "isAuthorizedJWT: error closing response body:", err)
a.log.ErrorLn(&cid,
"isAuthorizedJWT: error closing response body:", err)
}
}()

Expand All @@ -142,6 +145,7 @@ func (a *auth) isAuthorizedJWT(cid string, r *http.Request) bool {
return false
}

a.log.InfoLn(&cid, "isAuthorizedJWT: token is active:", tokenResponse.Active)
a.log.InfoLn(&cid,
"isAuthorizedJWT: token is active:", tokenResponse.Active)
return tokenResponse.Active
}
8 changes: 5 additions & 3 deletions app/sentinel/internal/oidc/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import (
"github.com/vmware-tanzu/secrets-manager/core/entity/v1/data"
)

// SafeOperations is an interface that defines the methods for safe operations.
// safeOperations is an interface that defines the methods for safe operations.
type safeOperations interface {
GetSecrets(ctx context.Context, r *http.Request, encrypt bool) (string, error)
UpdateSecrets(ctx context.Context, r *http.Request, cmd data.SentinelCommand) (string, error)
UpdateSecrets(ctx context.Context,
r *http.Request, cmd data.SentinelCommand) (string, error)
}

// Authorizer is an interface that defines the methods for authorizing requests.
Expand All @@ -38,7 +39,8 @@ func New(safeOps safeOperations, log logger) *Engine {
return newEngine(safeOps, newAuth(withLogger(log)), log)
}

// newEngine creates a new Engine instance with the provided safe operations, authorizer, and logger.
// newEngine creates a new Engine instance with the provided safe operations,
// authorizer, and logger.
// It is used internally by the NewEngine function to create the Engine instance.
// Better to use NewEngine function to create the Engine instance for unit testing.
func newEngine(safeOps safeOperations, auth authorizer, log logger) *Engine {
Expand Down
9 changes: 6 additions & 3 deletions app/sentinel/internal/oidc/engine/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ func (e *Engine) HandleSecrets(w http.ResponseWriter, r *http.Request) {

// handleListSecrets handles the listing of secrets.
// It retrieves the secrets from the safe and sends them to the client.
func (e *Engine) handleListSecrets(ctx context.Context, w http.ResponseWriter, r *http.Request, req *sentinel.SecretRequest) {
func (e *Engine) handleListSecrets(ctx context.Context,
w http.ResponseWriter, r *http.Request, req *sentinel.SecretRequest) {
secrets, err := e.safeOperations.GetSecrets(ctx, r, req.Encrypt)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
Expand Down Expand Up @@ -139,14 +140,16 @@ func (e *Engine) validateModifyRequest(req *sentinel.SecretRequest) error {
req.Namespaces = []string{defaultNamespace}
}

if !isValidSecretModification(req.Workloads, req.Encrypt, req.SerializedRootKeys, req.Secret, req.Delete) {
if !isValidSecretModification(req.Workloads, req.Encrypt,
req.SerializedRootKeys, req.Secret, req.Delete) {
return ErrInvalidInput
}
return nil
}

// createSentinelCommand creates a SentinelCommand from a SecretRequest.
func (e *Engine) createSentinelCommand(req *sentinel.SecretRequest) data.SentinelCommand {
func (e *Engine) createSentinelCommand(
req *sentinel.SecretRequest) data.SentinelCommand {
return data.SentinelCommand{
WorkloadIds: req.Workloads,
Secret: req.Secret,
Expand Down
3 changes: 2 additions & 1 deletion app/sentinel/internal/oidc/safe/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ func respond(cid *string, r *http.Response) (string, error) {
}
err := b.Close()
if err != nil {
log.Println(cid, "Post: Problem closing request body : %v", err.Error())
log.Println(cid, "Post: Problem closing request body : %v",
err.Error())
}
}(r.Body)

Expand Down
3 changes: 2 additions & 1 deletion app/sentinel/internal/oidc/safe/post.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ func Post(
proceed := <-proceedChan

if !proceed {
return "", printPayloadError(cid, errors.New("post: Could not proceed"))
return "", printPayloadError(cid,
errors.New("post: Could not proceed"))
}

authorizer := createAuthorizer()
Expand Down
Loading