Skip to content

Commit

Permalink
fix(new-e2e): Use the new definition of the secret test of ASC
Browse files Browse the repository at this point in the history
  • Loading branch information
chouetz committed Nov 14, 2024
1 parent 65d7d04 commit df3fe4e
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 13 deletions.
2 changes: 1 addition & 1 deletion test/new-e2e/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ require (
)

require (
github.com/DataDog/datadog-agent/pkg/util/optional v0.55.2
github.com/DataDog/datadog-agent/pkg/util/scrubber v0.58.2
github.com/pulumi/pulumi-aws/sdk/v6 v6.56.1
github.com/pulumi/pulumi-awsx/sdk/v2 v2.16.1
Expand All @@ -248,7 +249,6 @@ require (

require (
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/DataDog/datadog-agent/pkg/util/optional v0.55.2 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/aws/aws-sdk-go-v2/service/ecr v1.36.2 // indirect
github.com/pulumi/pulumi-azure-native-sdk/authorization/v2 v2.67.0 // indirect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import (

"github.com/DataDog/datadog-agent/test/new-e2e/pkg/e2e"
awshost "github.com/DataDog/datadog-agent/test/new-e2e/pkg/environments/aws/host"
secrets "github.com/DataDog/datadog-agent/test/new-e2e/tests/agent-shared-components/secretsutils"
"github.com/DataDog/test-infra-definitions/components/datadog/agentparams"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type linuxRuntimeSecretSuite struct {
Expand All @@ -28,28 +30,22 @@ func TestLinuxRuntimeSecretSuite(t *testing.T) {
//go:embed fixtures/secret_script.py
var secretScript []byte

func (v *linuxRuntimeSecretSuite) TestSecretRuntimeAPIKey() {
func (v *linuxRuntimeSecretSuite) TestSecretRuntimeHostname() {
config := `secret_backend_command: /tmp/bin/secret.sh
hostname: ENC[hostname]`

v.UpdateEnv(awshost.Provisioner(
awshost.WithAgentOptions(
agentparams.WithFile("/tmp/bin/secret.sh", string(secretScript), true),
),
))

v.Env().RemoteHost.MustExecute(`sudo sh -c "chown dd-agent:dd-agent /tmp/bin/secret.sh && chmod 700 /tmp/bin/secret.sh"`)
v.UpdateEnv(awshost.Provisioner(
awshost.WithAgentOptions(
agentparams.WithFileWithPermissions("/tmp/bin/secret.sh", string(secretScript), true, secrets.WithUnixSecretPermissions(false)),
agentparams.WithAgentConfig(config),
agentparams.WithFile("/tmp/bin/secret.sh", string(secretScript), true),
),
))

assert.EventuallyWithT(v.T(), func(t *assert.CollectT) {
checks, err := v.Env().FakeIntake.Client().GetCheckRun("datadog.agent.up")
assert.NoError(t, err)
assert.NotEmpty(t, checks)
assert.Equal(t, "e2e.test", checks[len(checks)-1].HostName)
require.NoError(t, err)
if assert.NotEmpty(t, checks) {
assert.Equal(t, "e2e.test", checks[len(checks)-1].HostName)
}
}, 30*time.Second, 2*time.Second)
}
53 changes: 53 additions & 0 deletions test/new-e2e/tests/agent-shared-components/secretsutils/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.

package secretsutils

import (
"path"
"testing"

"github.com/stretchr/testify/require"

"github.com/DataDog/datadog-agent/test/new-e2e/pkg/components"
)

// SecretClient is a client that can create and delete files containing secrets
type SecretClient struct {
t *testing.T
rootDir string
host *components.RemoteHost
}

// NewSecretClient creates a new SecretClient that can create and delete files containing secrets
func NewSecretClient(t *testing.T, host *components.RemoteHost, rootDir string) *SecretClient {
t.Log("Creating secret client with root directory", rootDir)
return &SecretClient{
t: t,
rootDir: rootDir,
host: host,
}
}

// SetSecret creates a new file containing the secret value
func (c *SecretClient) SetSecret(name string, value string) int64 {
c.t.Log("Setting secret", name)

// Create the root directory if it doesn't exist
err := c.host.MkdirAll(c.rootDir)
require.NoError(c.t, err)

fullpath := path.Join(c.rootDir, name)
b, err := c.host.WriteFile(fullpath, []byte(value))
require.NoError(c.t, err)
return b
}

// RemoveSecret deletes the file containing the secret
func (c *SecretClient) RemoveSecret(name string) error {
c.t.Log("Removing secret", name)
err := c.host.Remove(path.Join(c.rootDir, name))
return err
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env python3

import json
import os
import os.path
import sys


# this script resolves secret from disk
# a single argument should be given, the directory in which to look for secrets
# for each requested handle, it will try to read a file named as the handle in the directory
def main():
if len(sys.argv) != 2:
raise Exception("expected a single argument being the secret directory path")

cwd = sys.argv[1]

content = sys.stdin.read()
obj = json.loads(content)
handles = obj['secrets']

result = {}
for h in handles:
with open(os.path.join(cwd, h)) as reader:
key = reader.read().strip()
result[h] = {'value': key}

print(json.dumps(result))


if __name__ == '__main__':
main()
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@"C:\Program Files\Datadog\Datadog Agent\embedded3\python.exe" {{.PythonScriptPath}} %*
91 changes: 91 additions & 0 deletions test/new-e2e/tests/agent-shared-components/secretsutils/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.

// Package secretsutils contains utilities to manage secrets for e2e tests.
package secretsutils

import (
"bytes"
_ "embed"
"html/template"
"path/filepath"
"strings"

"github.com/DataDog/test-infra-definitions/components/datadog/agentparams"
perms "github.com/DataDog/test-infra-definitions/components/datadog/agentparams/filepermissions"

"github.com/DataDog/datadog-agent/pkg/util/optional"
)

//go:embed fixtures/secret-resolver.py
var secretResolverScript string

// WithUnixSecretSetupScript returns an agent param that setups a secret resolver script with correct permissions.
func WithUnixSecretSetupScript(path string, allowGroupExec bool) func(*agentparams.Params) error {
return agentparams.WithFileWithPermissions(path, secretResolverScript, true, WithUnixSecretPermissions(allowGroupExec))
}

// WithUnixSecretPermissions returns an UnixPermissions object containing correct permissions for a secret backend script.
func WithUnixSecretPermissions(allowGroupExec bool) optional.Option[perms.FilePermissions] {
if allowGroupExec {
return perms.NewUnixPermissions(perms.WithPermissions("0750"), perms.WithOwner("dd-agent"), perms.WithGroup("root"))
}

return perms.NewUnixPermissions(perms.WithPermissions("0700"), perms.WithOwner("dd-agent"), perms.WithGroup("dd-agent"))
}

//go:embed fixtures/secret_wrapper.bat
var secretWrapperScript string

// WithWindowsSecretSetupScript returns a list of agent params that setups a secret resolver script with correct permissions.
func WithWindowsSecretSetupScript(wrapperPath string, allowGroupExec bool) []func(*agentparams.Params) error {
// On Windows we're using a wrapper around the python script because we can't execute python scripts directly
// (this would require modifying permissions of the python binary)
// Basically the setup looks like this:
// <path>/
// ├── secret.py
// └── secret_wrapper.bat (specific permissions)

wrapperPath = strings.ReplaceAll(wrapperPath, `\`, `/`)

dir, _ := filepath.Split(wrapperPath)
pythonScriptPath := filepath.Join(dir, "secret.py")
secretWrapperContent := fillSecretWrapperTemplate(strings.ReplaceAll(pythonScriptPath, "/", "\\"))

return []func(*agentparams.Params) error{
agentparams.WithFileWithPermissions(wrapperPath, secretWrapperContent, true, WithWindowsSecretPermissions(allowGroupExec)),
agentparams.WithFile(pythonScriptPath, secretResolverScript, true),
}
}

// WithWindowsSecretPermissions returns a WindowsPermissions object containing correct permissions for a secret backend script.
func WithWindowsSecretPermissions(allowGroupExec bool) optional.Option[perms.FilePermissions] {
icaclsCmd := `/grant "ddagentuser:(RX)"`
if allowGroupExec {
icaclsCmd += ` "Administrators:(RX)"`
}

return perms.NewWindowsPermissions(perms.WithIcaclsCommand(icaclsCmd), perms.WithDisableInheritance())
}

// fillSecretWrapperTemplate fills the secret wrapper template with the correct path to the python script.
func fillSecretWrapperTemplate(pythonScriptPath string) string {
var buffer bytes.Buffer
var templateVars = map[string]string{
"PythonScriptPath": pythonScriptPath,
}

tmpl, err := template.New("").Parse(secretWrapperScript)
if err != nil {
panic("Could not parse secret wrapper template")
}

err = tmpl.Execute(&buffer, templateVars)
if err != nil {
panic("Could not fill variables in secret wrapper template")
}

return buffer.String()
}

0 comments on commit df3fe4e

Please sign in to comment.