Skip to content

Commit

Permalink
cli: deeper support for show-secrets in env get (#355)
Browse files Browse the repository at this point in the history
These changes plumb support for showing _all_ static secrets through
`esc env get` (rather than only those secrets immediately present in
the environment being read directly; i.e. including secrets from
imported environments).

Note that this support is latent, and the fix will not be user-visible
until supporting code is deployed to the ESC API.

Part of #347.
  • Loading branch information
pgavlin authored Jul 17, 2024
1 parent e84760b commit aab4e51
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 10 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@
- Coerce non-string scalars passed to `esc env set --secret` to strings
[#353](https://github.com/pulumi/esc/pull/353)

- `esc env get --show-secrets` now shows secrets from imported environments.
[#355](https://github.com/pulumi/esc/pull/355)

### Bug Fixes

14 changes: 10 additions & 4 deletions cmd/esc/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ func (c *testPulumiClient) getEnvironment(orgName, envName, version string) (*te
return env, env.revisions[revision-1], nil
}

func (c *testPulumiClient) checkEnvironment(ctx context.Context, orgName, envName string, yaml []byte) (*esc.Environment, []client.EnvironmentDiagnostic, error) {
func (c *testPulumiClient) checkEnvironment(ctx context.Context, orgName, envName string, yaml []byte, opts []client.CheckYAMLOption) (*esc.Environment, []client.EnvironmentDiagnostic, error) {
environment, diags, err := eval.LoadYAMLBytes(envName, yaml)
if err != nil {
return nil, nil, fmt.Errorf("loading environment: %w", err)
Expand All @@ -392,7 +392,12 @@ func (c *testPulumiClient) checkEnvironment(ctx context.Context, orgName, envNam
return nil, nil, fmt.Errorf("initializing the ESC exec context: %w", err)
}

checked, checkDiags := eval.CheckEnvironment(ctx, envName, environment, nil, providers, envLoader, execContext, false)
showSecrets := false
if len(opts) > 0 {
showSecrets = opts[0].ShowSecrets
}

checked, checkDiags := eval.CheckEnvironment(ctx, envName, environment, rot128{}, providers, envLoader, execContext, showSecrets)
diags.Extend(checkDiags...)
return checked, mapDiags(diags), nil
}
Expand Down Expand Up @@ -551,7 +556,7 @@ func (c *testPulumiClient) UpdateEnvironmentWithRevision(
return nil, 0, errors.New("tag mismatch")
}

_, diags, err := c.checkEnvironment(ctx, orgName, envName, yaml)
_, diags, err := c.checkEnvironment(ctx, orgName, envName, yaml, nil)
if err == nil && len(diags) == 0 {
h := fnv.New32()
h.Write(yaml)
Expand Down Expand Up @@ -601,8 +606,9 @@ func (c *testPulumiClient) CheckYAMLEnvironment(
ctx context.Context,
orgName string,
yaml []byte,
opts ...client.CheckYAMLOption,
) (*esc.Environment, []client.EnvironmentDiagnostic, error) {
return c.checkEnvironment(ctx, orgName, "<yaml>", yaml)
return c.checkEnvironment(ctx, orgName, "<yaml>", yaml, opts)
}

func (c *testPulumiClient) OpenYAMLEnvironment(
Expand Down
39 changes: 37 additions & 2 deletions cmd/esc/cli/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,18 @@ import (
const etagHeader = "ETag"
const revisionHeader = "Pulumi-ESC-Revision"

type CheckYAMLOption struct {
ShowSecrets bool
}

// Client provides a slim wrapper around the Pulumi HTTP/REST API.
//
// NOTE: this is not considered a public API, and we reserve the right to make breaking changes, including adding
// parameters, removing methods, changing types, etc.
//
// However, there is currently a cyclic dependency between the Pulumi CLI and the ESC CLI that causes breaking changes
// to any part of the client API to break the ESC CLI build. So we're limited to non-breaking changes, including adding
// variadic args or adding additional methods.
type Client interface {
// Insecure returns true if this client is insecure (i.e. has TLS disabled).
Insecure() bool
Expand Down Expand Up @@ -133,6 +144,7 @@ type Client interface {
ctx context.Context,
orgName string,
yaml []byte,
opts ...CheckYAMLOption,
) (*esc.Environment, []EnvironmentDiagnostic, error)

// OpenYAMLEnvironment evaluates the given environment YAML within the context of org orgName and
Expand Down Expand Up @@ -502,11 +514,27 @@ func (pc *client) CheckYAMLEnvironment(
ctx context.Context,
orgName string,
yaml []byte,
opts ...CheckYAMLOption,
) (*esc.Environment, []EnvironmentDiagnostic, error) {

// NOTE: ideally this method would take a plain old bool as its last parameter: it's not really a public API, so we
// reserve the right to make breaking changes, including adding parameters.
//
// However, there is currently a cyclic dependency between the Pulumi CLI and the ESC CLI that causes breaking changes
// to any part of the client API to break the ESC CLI build. So we're limited to non-breaking changes, including adding
// variadic args or adding additional methods.

path := fmt.Sprintf("/api/preview/environments/%v/yaml/check", orgName)

queryObj := struct {
ShowSecrets bool `url:"showSecrets"`
}{
ShowSecrets: firstOrDefault(opts).ShowSecrets,
}

var resp esc.Environment
var errResp EnvironmentErrorResponse
path := fmt.Sprintf("/api/preview/environments/%v/yaml/check", orgName)
err := pc.restCallWithOptions(ctx, http.MethodPost, path, nil, json.RawMessage(yaml), &resp, httpCallOptions{
err := pc.restCallWithOptions(ctx, http.MethodPost, path, queryObj, json.RawMessage(yaml), &resp, httpCallOptions{
ErrorResponse: &errResp,
})
if err != nil {
Expand Down Expand Up @@ -934,3 +962,10 @@ func IsNotFound(err error) bool {
resp, ok := err.(*apitype.ErrorResponse)
return ok && resp.Code == http.StatusNotFound
}

func firstOrDefault[T any](ts []T) (t T) {
if len(ts) > 0 {
return ts[0]
}
return t
}
7 changes: 4 additions & 3 deletions cmd/esc/cli/env_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"gopkg.in/yaml.v3"

"github.com/pulumi/esc"
"github.com/pulumi/esc/cmd/esc/cli/client"
"github.com/pulumi/esc/cmd/esc/cli/style"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/cmdutil"
Expand Down Expand Up @@ -147,7 +148,7 @@ func (get *envGetCommand) writeValue(
if err != nil {
return fmt.Errorf("getting environment definition: %w", err)
}
env, _, err := get.env.esc.client.CheckYAMLEnvironment(ctx, ref.orgName, def)
env, _, err := get.env.esc.client.CheckYAMLEnvironment(ctx, ref.orgName, def, client.CheckYAMLOption{ShowSecrets: showSecrets})
if err != nil {
return fmt.Errorf("getting environment: %w", err)
}
Expand Down Expand Up @@ -239,7 +240,7 @@ func (get *envGetCommand) getEntireEnvironment(
return &envGetTemplateData{Definition: string(def)}, nil
}

env, _, err := get.env.esc.client.CheckYAMLEnvironment(ctx, orgName, def)
env, _, err := get.env.esc.client.CheckYAMLEnvironment(ctx, orgName, def, client.CheckYAMLOption{ShowSecrets: showSecrets})
if err != nil {
return nil, fmt.Errorf("getting environment metadata: %w", err)
}
Expand Down Expand Up @@ -291,7 +292,7 @@ func (get *envGetCommand) getEnvironmentMember(
return &envGetTemplateData{Definition: def}, nil
}

env, _, err := get.env.esc.client.CheckYAMLEnvironment(ctx, orgName, def)
env, _, err := get.env.esc.client.CheckYAMLEnvironment(ctx, orgName, def, client.CheckYAMLOption{ShowSecrets: showSecrets})
if err != nil {
return nil, fmt.Errorf("getting environment metadata: %w", err)
}
Expand Down
51 changes: 50 additions & 1 deletion cmd/esc/cli/testdata/env-get-all.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ run: |
esc env get test@1
esc env get test@2
esc env get test@3
esc env get test@latest --show-secrets
environments:
test-user/a: {}
test-user/b: {}
test-user/b:
values:
baseSecret:
fn::secret:
ciphertext: ZXNjeAAAAAHz5ePy5fTB4+Pl8/PL5fnJxPD7
test-user/test:
revisions:
- yaml:
Expand Down Expand Up @@ -40,6 +45,7 @@ stdout: |+
"hello",
"world"
],
"baseSecret": "[secret]",
"boolean": true,
"null": null,
"number": 42,
Expand Down Expand Up @@ -80,6 +86,7 @@ stdout: |+
"hello",
"world"
],
"baseSecret": "[secret]",
"boolean": true,
"null": null,
"number": 42,
Expand Down Expand Up @@ -150,6 +157,7 @@ stdout: |+
"hello",
"world"
],
"baseSecret": "[secret]",
"boolean": true,
"null": null,
"number": 42,
Expand Down Expand Up @@ -182,10 +190,51 @@ stdout: |+
```
> esc env get test@latest --show-secrets
# Value
```json
{
"array": [
"hello",
"world"
],
"baseSecret": "secretAccessKey",
"boolean": true,
"null": null,
"number": 42,
"object": {
"hello": "world"
},
"open": "[unknown]",
"secret": "secretAccessKey",
"string": "esc"
}
```
# Definition
```yaml
imports:
- a
- b
values:
# comment
"null": null
boolean: true
number: 42
string: esc
array: [hello, world]
object: {hello: world}
open:
fn::open::test: echo
secret:
fn::secret: secretAccessKey
```
stderr: |
> esc env get test
> esc env get test@latest
> esc env get test@stable
> esc env get test@1
> esc env get test@2
> esc env get test@3
> esc env get test@latest --show-secrets

0 comments on commit aab4e51

Please sign in to comment.