Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Handle sensitive fields #77

Merged
merged 24 commits into from
Oct 7, 2021
Merged

Conversation

turkenh
Copy link
Member

@turkenh turkenh commented Sep 29, 2021

Description of your changes

This PR resolves handling sensitive fields in resource definition by generating appropriate schema (i.e. a secretRef for sensitive inputs and dropping fields from status), building connection details secret content, and constructing terraform attributes by gathering data from input/connection secrets.

Task list:

  • Extract field paths for fields marked as sensitive in resource schema
  • Get values matching field paths
  • Developers can add custom fields to be included in addition to whats is coming with schema
  • Generate GetConnectionDetails function in terraformed and verify sensitive fields landing in connection details secret
  • Adjust CRD schema for sensitive fields
    • If the sensitive field is a parameter, generate secret key ref in the schema
    • If the sensitive field is an observation, drop the field from the schema
  • Implement sensitive getting sensitive information back
    • Generate GetSensitiveObservation - returns data in connection details as terraform state attributes
    • Generate GetSensitiveParameters - returns data in the secrets referenced from parameter fields

Fixes #35

I have:

  • Read and followed Crossplane's [contribution process].
  • Run make reviewable to ensure this PR is ready for review.
  • Added backport release-x.y labels to auto-backport this PR if necessary.

How has this code been tested

Tested with the following provider-tf-aws PR: crossplane-contrib/provider-jet-aws#24

turkenh added 14 commits October 5, 2021 13:46
@turkenh turkenh marked this pull request as ready for review October 5, 2021 10:55
@turkenh turkenh requested review from muvaf and ulucinar and removed request for muvaf October 5, 2021 11:18
Copy link
Member

@muvaf muvaf left a comment

Choose a reason for hiding this comment

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

Awesome to see the whole sensitive information issue including user input getting resolved!

pkg/terraform/files.go Outdated Show resolved Hide resolved
pkg/controller/secretclient.go Show resolved Hide resolved
pkg/pipeline/crd.go Outdated Show resolved Hide resolved
pkg/resource/sensitive.go Outdated Show resolved Hide resolved
pkg/resource/sensitive.go Outdated Show resolved Hide resolved
return nil
}

func expandedTFPath(expandedXP string, mapping map[string]string) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

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

If I understood correctly, this function takes an expanded JSON path and returns a TF path that you can use to set a value on a TF file. I wonder if we can get away with some string manipulation here to replace the field names. Do you think something like this worth testing?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the suggestion and for preparing the code snippet.

I'll try if I can simplify following an approach you suggested, however, one caveat here is, fieldpath.Paved does not print keys of maps inside [ ] if the key contains dots. See this as an example. So, initially, I attempted some regex replace kind of solution but I ended up parsing them using the same parsing not to miss something or build a complex method to handle edge cases like I mentioned.

Copy link
Member Author

Choose a reason for hiding this comment

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

I had another look. Actual complexity came from identifying expandedJSON is for which wildcarded fieldpath due to the inconsistent printing behaviour I mentioned above (see possible values for expandedJSON), which is currently handled by expandedFor function.
I think it wouldn't worth to use replacer solution given we already have to parse fieldpath to segments.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm I didn't think of the case where there is a string as index actually. We'd have to make it not consider strings between [ and ] during replace, which could be more complex as you said. Thanks for testing it!

pkg/types/builder.go Outdated Show resolved Hide resolved
fieldNameCamel := fieldName.Camel
if e, ix := containsAt(cfg.Sensitive.CustomFieldPaths, tfFieldPath); e || sch.Sensitive {
if e {
cfg.Sensitive.CustomFieldPaths = remove(cfg.Sensitive.CustomFieldPaths, ix)
Copy link
Member

Choose a reason for hiding this comment

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

Would it make sense to use map[string]string instead of []string as type of CustomFieldPaths, then merge it into fieldPaths directly? It could be easier to work with if there was a single map that we need to use here. I didn't try to see whether it works, just an idea you might want to consider.

Copy link
Member Author

Choose a reason for hiding this comment

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

This was something I considered but I didn't like that users would need to provide a map in that case and the value part of the map (xp/json path) is even unknown before the code generation. We could expect them to set some placeholder (or empty?) values but that sounded hacky.
But anyway, as we discussed today, I will need to revisit getting custom configuration since we would need the distinction of include into connection details but not sensitive type of fields.

pkg/types/builder.go Show resolved Hide resolved
pkg/types/builder.go Show resolved Hide resolved
pkg/types/builder.go Outdated Show resolved Hide resolved
@turkenh
Copy link
Member Author

turkenh commented Oct 6, 2021

Thanks for the review @muvaf! Resolved/responded to all your comments.

The two open items I need to add to PR is:

  • Always include id in connection details
  • Ability to configure fields to get into connection but not mark as sensitive (i.e. no schema change)

@turkenh turkenh requested a review from muvaf October 6, 2021 22:02
pkg/types/builder.go Outdated Show resolved Hide resolved
// Data will be stored in connection details secret
continue
}
sfx := "SecretRef"
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit:
Just for consideration: If the field name already ends with secret, we will have something like xyzSecretSecretRef.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, but not sure xyzSecretRef would be better in such a case or are there any better alternative

Copy link
Member

@muvaf muvaf left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks @turkenh !

pkg/pipeline/templates/terraformed.go.tmpl Show resolved Hide resolved
pkg/pipeline/templates/terraformed.go.tmpl Outdated Show resolved Hide resolved
pkg/pipeline/templates/terraformed.go.tmpl Outdated Show resolved Hide resolved
return err
}
xpParams := map[string]interface{}{}
if err = pv.GetValueInto("spec.forProvider", &xpParams); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

Right now it looks like the following:

map[string]string{"master_password": "masterPasswordSecretRef"}

In TFState, master_password is at the top level in HCL of the resource definition, whereas spec.forProvider.masterPasswordSecretRef would have been the fully qualified path for the Crossplane definition. Both work but the latter is correct in the sense that it's ready to be used in all possible contexts whereas if we have only masterPasswordSecretRef, we'd need to know the prefix that's needed to use to actually access the data.

pkg/controller/secretclient.go Show resolved Hide resolved
return nil
}

func expandedTFPath(expandedXP string, mapping map[string]string) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

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

Hmm I didn't think of the case where there is a string as index actually. We'd have to make it not consider strings between [ and ] during replace, which could be more complex as you said. Thanks for testing it!

pkg/types/builder.go Show resolved Hide resolved
@turkenh turkenh merged commit 95b2d12 into crossplane:main Oct 7, 2021
@turkenh turkenh deleted the sensitive-fields branch October 7, 2021 10:54
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Figure out how to handle sensitive information for managed resources
3 participants