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

Adding secretsmanager support #305

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

RealHarshThakur
Copy link
Contributor

@RealHarshThakur RealHarshThakur commented Feb 21, 2021

Signed-off-by: Harsh Thakur harshthakur9030@gmail.com

Description of your changes

Fixes ##294

I have:

  • Read and followed Crossplane's contribution process.
  • [] Run make reviewable test to ensure this PR is ready for review.

TODO:

  • Implement type SecretVersion . This is where data is going to reside
  • Add Kubernetes SecretRef

How has this code been tested

  • Add unit tests

Manually tried creating, updating, syncing and deleting the secret(GCP) resource.
Manually tried creating a secret version , changed it's states and deleting the secret version

@RealHarshThakur RealHarshThakur marked this pull request as draft February 21, 2021 19:09
@RealHarshThakur RealHarshThakur changed the title Adding resource : secret Adding secretsmanager support Feb 21, 2021
@RealHarshThakur RealHarshThakur force-pushed the secrets-manager branch 2 times, most recently from 3704dd3 to d369831 Compare February 25, 2021 21:51
Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
Copy link
Member

@hasheddan hasheddan left a comment

Choose a reason for hiding this comment

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

@RealHarshThakur thanks for working on this and apologies for the review delay! I think we should be offering two different CRDs here to match the GCP API (Secret and SecretVersion).

Some helpful references could be the similar implementation in provider-aws as well as the terraform docs for this API.

apis/secretsmanager/v1alpha1/secret_types.go Outdated Show resolved Hide resolved
apis/secretsmanager/v1alpha1/secret_types.go Outdated Show resolved Hide resolved
apis/secretsmanager/v1alpha1/secret_types.go Outdated Show resolved Hide resolved
Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
@RealHarshThakur RealHarshThakur marked this pull request as ready for review March 22, 2021 18:16
Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
Copy link
Member

@hasheddan hasheddan left a comment

Choose a reason for hiding this comment

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

Thanks so much for working on this @RealHarshThakur! Let me know if you have any questions :)


// Required. The resource name of the project to associate with the
// [Secret][google.cloud.secretmanager.v1.Secret], in the format `projects/*`.
Parent string `json:"parent,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

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

If required we don't need omitempty.

Suggested change
Parent string `json:"parent,omitempty"`
Parent string `json:"parent"`

Copy link
Member

Choose a reason for hiding this comment

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

This should also be a cross resource reference to the Secret type.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I didn't understand the cross resource reference part . Is it possible to reference just the field Secret.ObjectMeta.Name ?

}

// ReplicationAutomatic has fields for automatic replication of secrets
type ReplicationAutomatic struct {
Copy link
Member

Choose a reason for hiding this comment

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

Should there be fields here?

Copy link
Contributor Author

@RealHarshThakur RealHarshThakur Apr 4, 2021

Choose a reason for hiding this comment

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

The current version of google SDK doesn't have any but there are new fields in the latest versions. Shall I add a comment to mention it's intentionally empty?

type ReplicationUserManagedReplica struct {
// Location of the secret.
// +immutable
Location string `json:"location,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

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

Should be pointer type if optional, though if it is the only field in this embedded struct we could consider making it required and just the parent struct optional.

Suggested change
Location string `json:"location,omitempty"`
Location *string `json:"location,omitempty"`

Copy link
Contributor Author

@RealHarshThakur RealHarshThakur Apr 5, 2021

Choose a reason for hiding this comment

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

Yes, making the struct optional reflects what GCP expects. If user has started filling the struct, Location should be a required field. Also, newer GCP SDK does have additional fields . I have already marked this as optional in ReplicationType struct at L67


// Output only. This must be unique within the project. External name of the object is set to this field, hence making it optional
// +optional
SecretID *string `json:"secretid,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
SecretID *string `json:"secretid,omitempty"`
SecretID string `json:"secretid,omitempty"`

We typically do not use pointer types in status.

Copy link
Contributor Author

@RealHarshThakur RealHarshThakur Apr 5, 2021

Choose a reason for hiding this comment

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

I am wondering if I should remove this field as it doesn't provide much value anyway. It's the same as external name of the CR


const (
// SecretVersionSTATEUNSPECIFIED represents that SecretVersion state is not specified. This value is unused and invalid.
SecretVersionSTATEUNSPECIFIED SecretVersionState = 0
Copy link
Member

Choose a reason for hiding this comment

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

Can we make this camel case?

Suggested change
SecretVersionSTATEUNSPECIFIED SecretVersionState = 0
SecretVersionStateUnspecified SecretVersionState = 0

type SecretVersionParameters struct {
// SecretRef refers to the secret object(GCP) created in Kubernetes
// Required
SecretRef string `json:"secretRef,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

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

Should this be optional if payload is provided?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, the comment is misleading, SecretRef is the name of the secret created within GCP . Basically, the secrets manager expects us to create a Secret and then it can have multiple SecretVersion . It won't be possible to create a SecretVersion without the Secret . End users can choose to create the Secret manually and just manage SecretVersion through crossplane

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For referencing K8s secret, I am continuing the work here : #317 .

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, I wonder if there's a way to enforce the following validation: it is mandatory to pass in either Payload or KubeSecretRef . Right now, I have kept them both optional

// SecretVersionDESTROYED represents that SecretVersion state is destroyed and the secret data is no longer
// stored. A version may not leave this state once entered.
// SecretVersionDESTROYED SecretVersionState = 3
// +kubebuilder:validation:Enum=1;2;3
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we should instead make this ENABLED,DISABLED,... as that would likely map to the experience folks would expect here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

"github.com/crossplane/provider-gcp/apis/secretversion/v1alpha1"
"github.com/google/go-cmp/cmp"
"github.com/googleapis/gax-go"
"google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
Copy link
Member

Choose a reason for hiding this comment

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

I think both Secret and SecretVersion should be in secretmanager group, just be different types within it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

Comment on lines 26 to 30
// Package type metadata.
const (
Group = "secretsmanager.gcp.crossplane.io"
Version = "v1alpha1"
)
Copy link
Member

Choose a reason for hiding this comment

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

I left the same comment below in the client packages, but I think both Secret and SecretVersion should be in the secretsmanager.gcp.crossplane.io group and just be different types, rather than in different groups.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, I should probably change the project structure too in clients and controllers too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

Copy link
Contributor Author

@RealHarshThakur RealHarshThakur left a comment

Choose a reason for hiding this comment

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

@hasheddan Thanks for reviewing . Will work on the suggestions and start with writing tests

Comment on lines 26 to 30
// Package type metadata.
const (
Group = "secretsmanager.gcp.crossplane.io"
Version = "v1alpha1"
)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, I should probably change the project structure too in clients and controllers too.


// Required. The resource name of the project to associate with the
// [Secret][google.cloud.secretmanager.v1.Secret], in the format `projects/*`.
Parent string `json:"parent,omitempty"`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I didn't understand the cross resource reference part . Is it possible to reference just the field Secret.ObjectMeta.Name ?

}

// ReplicationAutomatic has fields for automatic replication of secrets
type ReplicationAutomatic struct {
Copy link
Contributor Author

@RealHarshThakur RealHarshThakur Apr 4, 2021

Choose a reason for hiding this comment

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

The current version of google SDK doesn't have any but there are new fields in the latest versions. Shall I add a comment to mention it's intentionally empty?

type ReplicationUserManagedReplica struct {
// Location of the secret.
// +immutable
Location string `json:"location,omitempty"`
Copy link
Contributor Author

@RealHarshThakur RealHarshThakur Apr 5, 2021

Choose a reason for hiding this comment

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

Yes, making the struct optional reflects what GCP expects. If user has started filling the struct, Location should be a required field. Also, newer GCP SDK does have additional fields . I have already marked this as optional in ReplicationType struct at L67


// Output only. This must be unique within the project. External name of the object is set to this field, hence making it optional
// +optional
SecretID *string `json:"secretid,omitempty"`
Copy link
Contributor Author

@RealHarshThakur RealHarshThakur Apr 5, 2021

Choose a reason for hiding this comment

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

I am wondering if I should remove this field as it doesn't provide much value anyway. It's the same as external name of the CR

type SecretVersionParameters struct {
// SecretRef refers to the secret object(GCP) created in Kubernetes
// Required
SecretRef string `json:"secretRef,omitempty"`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, the comment is misleading, SecretRef is the name of the secret created within GCP . Basically, the secrets manager expects us to create a Secret and then it can have multiple SecretVersion . It won't be possible to create a SecretVersion without the Secret . End users can choose to create the Secret manually and just manage SecretVersion through crossplane

type SecretVersionParameters struct {
// SecretRef refers to the secret object(GCP) created in Kubernetes
// Required
SecretRef string `json:"secretRef,omitempty"`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

For referencing K8s secret, I am continuing the work here : #317 .

type SecretVersionParameters struct {
// SecretRef refers to the secret object(GCP) created in Kubernetes
// Required
SecretRef string `json:"secretRef,omitempty"`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, I wonder if there's a way to enforce the following validation: it is mandatory to pass in either Payload or KubeSecretRef . Right now, I have kept them both optional

Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
Signed-off-by: Harsh Thakur <harshthakur9030@gmail.com>
Copy link
Member

@hasheddan hasheddan left a comment

Choose a reason for hiding this comment

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

@RealHarshThakur thanks for your patience here and my apologies on the long review cycle 😞 We have made a number of changes in this repo in #308 which will require a rebase here. Please let me know if you have any questions and I will be more than happy to help :)

I also noticed you are using the genproto GCP library here. I recently moved a few of our types off of it because it was somewhat difficult to work with (you may have noticed this in the steps required in the controller implementation). It may be easier to work with https://github.com/googleapis/google-api-go-client/blob/d82b0a56bb37a94bfd6d885bc7c3e1761de7b509/secretmanager/v1/secretmanager-gen.go#L1187 instead. I believe we are now on the latest version of this package 👍

@turkenh
Copy link
Contributor

turkenh commented Sep 6, 2021

@RealHarshThakur what is your plan on this one? Do you have some time to revisit/rebase this PR?

@RealHarshThakur
Copy link
Contributor Author

Hey @turkenh , the PR is almost ready. I need to add bits to reference K8s secrets, but I was doing in a separate PR. Sure, I can rebase it but I can't test it against GCP API anymore due to weird billing issue.

@knelasevero
Copy link

@RealHarshThakur I can help testing agains gcp API in my account if it would help. Would love to see this merged :)

@RealHarshThakur
Copy link
Contributor Author

RealHarshThakur commented Oct 27, 2021

@knelasevero Awesome. Do you need any help from me?
I could give you access to this branch.(I don't know if there's a better way to collaborate)

UPDATE: invited you to my fork. Feel free to push commits directly.

@knelasevero
Copy link

@RealHarshThakur Thanks! I just accepted. I will be working on this next week.

@RealHarshThakur
Copy link
Contributor Author

@knelasevero Great! JFYI: I did try to have a K8s secret reference in a separate PR. #317 .
I think there are some bits in it which still need thinking as there's no direct way to enforce immutability of fields but would love to hear your experience/opinion on it.

@knelasevero
Copy link

Hey, sorry to have vanished. I've been on sick leave for a while.

@RealHarshThakur do you think we can pair on this when I am back? I think we can close this one quicker that way

@RealHarshThakur
Copy link
Contributor Author

Sure, shoot me an email ( harshthakur9030@gmail.com ) or at crossplane slack so we can figure out a time

@knelasevero
Copy link

Ok, I thought I would have more time, but client work will get most of my slots. Would you have time to rebase yourself and tweak whatever is needed? Then you can let me know and I test this in my account.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants