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

Automatically mark Secret data and stringData as secret #803

Merged
merged 2 commits into from
Sep 19, 2019
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

### Improvements

- Automatically mark Secret data and stringData as secret. (https://github.com/pulumi/pulumi-kubernetes/pull/803).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add clarifying docs that this secret encoding only applies to the statefile, as the secret will still be stored in plaintext or b64 in k8s and etcd by default.

As of 1.13 there is a beta feature for encryption at rest for etcd, assuming the user can enable this feature. This would also be a good time to remind folks to lock down etcd and control plane access to admins only if possible - see risks.

IMO we should present both links ^ in the docs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@metral Which docs were you thinking? The SDK docs for the Secret class?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was leaning towards the ones linked in my prior comment. Figured this would be a good opportunity to nudge the user to consider reading both links and applying them if possible

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment to the SDK docs for the Secret classes.

- Provide detailed error for removed apiVersions. (https://github.com/pulumi/pulumi-kubernetes/pull/809).

## 1.1.0 (September 18, 2019)
Expand Down
76 changes: 48 additions & 28 deletions pkg/gen/additionalComments.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,39 +23,38 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
)

func timeoutComment(kind kinds.Kind) string {
const timeoutOverride = `setting the 'customTimeouts' option on the resource.`

var v int
switch kind {
case kinds.Deployment:
v = await.DefaultDeploymentTimeoutMins
case kinds.Ingress:
v = await.DefaultIngressTimeoutMins
case kinds.Pod:
v = await.DefaultPodTimeoutMins
case kinds.Service:
v = await.DefaultServiceTimeoutMins
case kinds.StatefulSet:
v = await.DefaultStatefulSetTimeoutMins
default:
// No timeout defined for other resource Kinds.
return ""
}
timeoutStr := strconv.Itoa(v) + " minutes"

return fmt.Sprintf(`
If the %s has not reached a Ready state after %s, it will
time out and mark the resource update as Failed. You can override the default timeout value
by %s`, kind, timeoutStr, timeoutOverride)
}

func awaitComments(kind kinds.Kind) string {
const preamble = `This resource waits until it is ready before registering success for
create/update and populating output properties from the current state of the resource.
The following conditions are used to determine whether the resource creation has
succeeded or failed:
`
timeoutComment := func(kind kinds.Kind) string {
const timeoutOverride = `setting the 'customTimeouts' option on the resource.`

var v int
switch kind {
case kinds.Deployment:
v = await.DefaultDeploymentTimeoutMins
case kinds.Ingress:
v = await.DefaultIngressTimeoutMins
case kinds.Pod:
v = await.DefaultPodTimeoutMins
case kinds.Service:
v = await.DefaultServiceTimeoutMins
case kinds.StatefulSet:
v = await.DefaultStatefulSetTimeoutMins
default:
// No timeout defined for other resource Kinds.
return ""
}
timeoutStr := strconv.Itoa(v) + " minutes"

return fmt.Sprintf(`
If the %s has not reached a Ready state after %s, it will
time out and mark the resource update as Failed. You can override the default timeout value
by %s`, kind, timeoutStr, timeoutOverride)
}

comment := preamble
switch kind {
Expand Down Expand Up @@ -128,13 +127,34 @@ out. To work around this limitation, set 'pulumi.com/skipAwait: "true"' on
return comment
}

func AwaitComment(kind string) string {
func helpfulLinkComments(kind kinds.Kind) string {
switch kind {
case kinds.Secret:
return `Note: While Pulumi automatically encrypts the 'data' and 'stringData'
fields, this encryption only applies to Pulumi's context, including the state file,
the Service, the CLI, etc. Kubernetes does not encrypt Secret resources by default,
and the contents are visible to users with access to the Secret in Kubernetes using
tools like 'kubectl'.

For more information on securing Kubernetes Secrets, see the following links:
https://kubernetes.io/docs/concepts/configuration/secret/#security-properties
https://kubernetes.io/docs/concepts/configuration/secret/#risks`
default:
return ""
}
}

// PulumiComment adds additional information to the docs generated automatically from the OpenAPI specs.
// This includes information about Pulumi's await behavior, deprecation information, etc.
func PulumiComment(kind string) string {
const prefix = "\n\n"

k := kinds.Kind(kind)
switch k {
case kinds.Deployment, kinds.Ingress, kinds.Job, kinds.Pod, kinds.Service, kinds.StatefulSet:
return prefix + awaitComments(k)
case kinds.Secret:
return prefix + helpfulLinkComments(k)
default:
return ""
}
Expand Down
10 changes: 9 additions & 1 deletion pkg/gen/nodejs-templates/kind.ts.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as outputs from "../../types/output";
import { getVersion } from "../../version";

/**
* {{{Comment}}}{{{AwaitComment}}}
* {{{Comment}}}{{{PulumiComment}}}
*/
export class {{Kind}} extends pulumi.CustomResource {
{{#Properties}}
Expand Down Expand Up @@ -72,6 +72,14 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
{{#AdditionalSecretOutputs}}
"{{.}}",
{{/AdditionalSecretOutputs}}
...((opts && opts.additionalSecretOutputs) || []),

];
super({{Kind}}.__pulumiType, name, props, opts);
}
}
3 changes: 2 additions & 1 deletion pkg/gen/nodejs.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ func NodeJSClient(swagger map[string]interface{}, templateDir string,
"Properties": kind.Properties(),
"RequiredInputProperties": kind.RequiredInputProperties(),
"OptionalInputProperties": kind.OptionalInputProperties(),
"AdditionalSecretOutputs": kind.AdditionalSecretOutputs(),
"URNAPIVersion": kind.URNAPIVersion(),
"Version": version.Version(),
"AwaitComment": kind.awaitComment,
"PulumiComment": kind.pulumiComment,
})
if err != nil {
return "", "", "", "", "", nil, err
Expand Down
11 changes: 10 additions & 1 deletion pkg/gen/python-templates/kind.py.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ from ... import tables, version

class {{Kind}}(pulumi.CustomResource):
"""
{{{Comment}}}{{{AwaitComment}}}
{{{Comment}}}{{{PulumiComment}}}
"""

apiVersion: pulumi.Output[str]
Expand Down Expand Up @@ -76,6 +76,15 @@ class {{Kind}}(pulumi.CustomResource):

__props__['status'] = None

additional_secret_outputs = [
{{#AdditionalSecretOutputs}}
"{{.}}",
{{/AdditionalSecretOutputs}}
]

opts = pulumi.ResourceOptions.merge(opts, pulumi.ResourceOptions(
version=version.get_version(), additional_secret_outputs=additional_secret_outputs))

opts = pulumi.ResourceOptions.merge(opts, pulumi.ResourceOptions(version=version.get_version()))

super({{Kind}}, self).__init__(
Expand Down
26 changes: 22 additions & 4 deletions pkg/gen/typegen.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/ahmetb/go-linq"
"github.com/jinzhu/copier"
"github.com/mitchellh/go-wordwrap"
"github.com/pulumi/pulumi-kubernetes/pkg/kinds"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"

Expand Down Expand Up @@ -134,10 +135,11 @@ func (vc *VersionConfig) RawAPIVersion() string { return vc.rawAPIVersion }
type KindConfig struct {
kind string
comment string
awaitComment string
pulumiComment string
properties []*Property
requiredInputProperties []*Property
optionalInputProperties []*Property
additionalSecretOutputs []string

gvk *schema.GroupVersionKind // Used for sorting.
apiVersion string
Expand All @@ -152,8 +154,8 @@ func (kc *KindConfig) Kind() string { return kc.kind }
// Comment returns the comments associated with some Kubernetes API kind.
func (kc *KindConfig) Comment() string { return kc.comment }

// AwaitComment returns the await logic documentation associated with some Kubernetes API kind.
func (kc *KindConfig) AwaitComment() string { return kc.awaitComment }
// PulumiComment returns the await logic documentation associated with some Kubernetes API kind.
func (kc *KindConfig) PulumiComment() string { return kc.pulumiComment }

// Properties returns the list of properties that exist on some Kubernetes API kind (i.e., things
// that we will want to `.` into, like `thing.apiVersion`, `thing.kind`, `thing.metadata`, etc.).
Expand All @@ -167,6 +169,10 @@ func (kc *KindConfig) RequiredInputProperties() []*Property { return kc.required
// Kubernetes API kind (i.e., things that we will want to provide, like `thing.metadata`, etc.).
func (kc *KindConfig) OptionalInputProperties() []*Property { return kc.optionalInputProperties }

// AdditionalSecretOutputs returns the list of strings to set as additionalSecretOutputs on some
// Kubernetes API kind.
func (kc *KindConfig) AdditionalSecretOutputs() []string { return kc.additionalSecretOutputs }

// APIVersion returns the fully-qualified apiVersion (e.g., `storage.k8s.io/v1` for storage, etc.)
func (kc *KindConfig) APIVersion() string { return kc.apiVersion }

Expand Down Expand Up @@ -824,10 +830,11 @@ func createGroups(definitionsJSON map[string]interface{}, opts groupOpts) []*Gro
// NOTE: This transformation assumes git users on Windows to set
// the "check in with UNIX line endings" setting.
comment: fmtComment(d.data["description"], " ", true, opts, d.gvk),
awaitComment: fmtComment(AwaitComment(d.gvk.Kind), prefix, true, opts, d.gvk),
pulumiComment: fmtComment(PulumiComment(d.gvk.Kind), prefix, true, opts, d.gvk),
properties: properties,
requiredInputProperties: requiredInputProperties,
optionalInputProperties: optionalInputProperties,
additionalSecretOutputs: additionalSecretOutputs(d.gvk),
gvk: &d.gvk,
apiVersion: fqGroupVersion,
rawAPIVersion: defaultGroupVersion,
Expand Down Expand Up @@ -900,3 +907,14 @@ func createGroups(definitionsJSON map[string]interface{}, opts groupOpts) []*Gro

return groups
}

func additionalSecretOutputs(gvk schema.GroupVersionKind) []string {
kind := kinds.Kind(gvk.Kind)

switch kind {
case kinds.Secret:
return []string{"data", "stringData"}
default:
return []string{}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(MutatingWebhookConfiguration.__pulumiType, name, props, opts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(MutatingWebhookConfigurationList.__pulumiType, name, props, opts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(ValidatingWebhookConfiguration.__pulumiType, name, props, opts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(ValidatingWebhookConfigurationList.__pulumiType, name, props, opts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(MutatingWebhookConfiguration.__pulumiType, name, props, opts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(MutatingWebhookConfigurationList.__pulumiType, name, props, opts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(ValidatingWebhookConfiguration.__pulumiType, name, props, opts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(ValidatingWebhookConfigurationList.__pulumiType, name, props, opts);
}
}
5 changes: 5 additions & 0 deletions sdk/nodejs/apiextensions/v1/CustomResourceDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(CustomResourceDefinition.__pulumiType, name, props, opts);
}
}
5 changes: 5 additions & 0 deletions sdk/nodejs/apiextensions/v1/CustomResourceDefinitionList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(CustomResourceDefinitionList.__pulumiType, name, props, opts);
}
}
5 changes: 5 additions & 0 deletions sdk/nodejs/apiextensions/v1beta1/CustomResourceDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(CustomResourceDefinition.__pulumiType, name, props, opts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(CustomResourceDefinitionList.__pulumiType, name, props, opts);
}
}
5 changes: 5 additions & 0 deletions sdk/nodejs/apiregistration/v1/APIService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ import { getVersion } from "../../version";
if (!opts.version) {
opts.version = getVersion();
}

opts.additionalSecretOutputs = [
...((opts && opts.additionalSecretOutputs) || []),

];
super(APIService.__pulumiType, name, props, opts);
}
}
Loading