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

Commit

Permalink
Finalize GetSensitiveObservation/Parameters
Browse files Browse the repository at this point in the history
Signed-off-by: Hasan Turken <[email protected]>
  • Loading branch information
turkenh committed Oct 5, 2021
1 parent f132952 commit 9e116bb
Show file tree
Hide file tree
Showing 5 changed files with 397 additions and 69 deletions.
38 changes: 9 additions & 29 deletions pkg/conversion/secretclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,47 +10,27 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)

type APISecretClientOption func(*APISecretClient)

func WithDefaultNamespace(n string) APISecretClientOption {
return func(a *APISecretClient) {
a.defaultNamespace = n
}
}

// APISecretClient is a client for getting k8s secrets
type APISecretClient struct {
kube client.Client
defaultNamespace string
kube client.Client
}

func NewAPISecretClient(k client.Client, opts ...APISecretClientOption) *APISecretClient {
a := &APISecretClient{
kube: k,
defaultNamespace: "crossplane-system",
}

for _, o := range opts {
o(a)
}

return a
// NewAPISecretClient builds and returns a new APISecretClient
func NewAPISecretClient(k client.Client) *APISecretClient {
return &APISecretClient{kube: k}
}

func (a *APISecretClient) GetSecretData(ctx context.Context, s xpv1.SecretReference) (map[string][]byte, error) {
if s.Namespace == "" {
s.Namespace = a.defaultNamespace
}
// GetSecretData gets and returns data for the referenced secret
func (a *APISecretClient) GetSecretData(ctx context.Context, ref xpv1.SecretReference) (map[string][]byte, error) {
secret := &v1.Secret{}
if err := a.kube.Get(ctx, types.NamespacedName{Namespace: s.Namespace, Name: s.Name}, secret); err != nil {
if err := a.kube.Get(ctx, types.NamespacedName{Namespace: ref.Namespace, Name: ref.Name}, secret); err != nil {
return nil, err
}
return secret.Data, nil
}

// GetSecretValue gets and returns value for key of the referenced secret
func (a *APISecretClient) GetSecretValue(ctx context.Context, sel xpv1.SecretKeySelector) ([]byte, error) {
if sel.Namespace == "" {
sel.Namespace = a.defaultNamespace
}
d, err := a.GetSecretData(ctx, sel.SecretReference)
if err != nil {
return nil, errors.Wrap(err, "cannot get secret data")
Expand Down
28 changes: 13 additions & 15 deletions pkg/generate.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
/*
Copyright 2021 The Crossplane Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Copyright 2021 Upbound Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build generate

Expand Down
6 changes: 3 additions & 3 deletions pkg/terraform/resource/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Copyright 2021 The Crossplane Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
You may obtain a copy of the License mapping
http://www.apache.org/licenses/LICENSE-2.0
Expand All @@ -26,7 +26,7 @@ import (
// SecretClient is the client to get sensitive data from kubernetes secrets
//go:generate go run github.com/golang/mock/mockgen -copyright_file ../../../hack/boilerplate.txt -destination ./mocks/resource.go -package mocks github.com/crossplane-contrib/terrajet/pkg/terraform/resource SecretClient
type SecretClient interface {
GetSecretData(ctx context.Context, s v1.SecretReference) (map[string][]byte, error)
GetSecretData(ctx context.Context, ref v1.SecretReference) (map[string][]byte, error)
GetSecretValue(ctx context.Context, sel v1.SecretKeySelector) ([]byte, error)
}

Expand All @@ -41,6 +41,7 @@ type Observable interface {
type Parameterizable interface {
GetParameters(ctx context.Context, c SecretClient) (map[string]interface{}, error)
SetParameters(map[string]interface{}) error
GetConnectionDetails(map[string]interface{}) (map[string][]byte, error)
}

// MetadataProvider provides Terraform metadata for the Terraform managed resource
Expand All @@ -63,6 +64,5 @@ type Terraformed interface {
MetadataProvider
Observable
Parameterizable
SensitiveDataProvider
LateInitializer
}
144 changes: 123 additions & 21 deletions pkg/terraform/resource/sensitive.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
Copyright 2021 The Crossplane Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License mapping
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package resource

import (
Expand Down Expand Up @@ -54,46 +70,132 @@ func stringsMatchingFieldPath(from map[string]interface{}, path string) (map[str

// GetSensitiveParameters will collect sensitive information as terraform state
// attributes by following secret references in the spec.
func GetSensitiveParameters(ctx context.Context, client SecretClient, from runtime.Object, into map[string]interface{}, at map[string]string) error {
func GetSensitiveParameters(ctx context.Context, client SecretClient, from runtime.Object, into map[string]interface{}, mapping map[string]string) error {
pv, err := fieldpath.PaveObject(from)
if err != nil {
return err
}
//paveXP, err := pv.GetValue("spec.forProvider")
if err != nil {
xpParams := map[string]interface{}{}
if err = pv.GetValueInto("spec.forProvider", &xpParams); err != nil {
return err
}
paveXP := fieldpath.Pave(xpParams)
paveTF := fieldpath.Pave(into)

/* for tf, xp := range at {
}*/

for k, v := range at {
sel := v1.SecretKeySelector{}
sel.Name, err = pv.GetString("spec.forProvider." + v + ".name")
var sensitive []byte
for tf, xp := range mapping {
expXPs, err := paveXP.ExpandWildcards(xp)
if err != nil {
return err
return errors.Wrapf(err, "cannot expand wildcard for xp resource")
}
sel.Key, err = pv.GetString("spec.forProvider." + v + ".key")
if err != nil {
return err
for _, expXP := range expXPs {
sel := v1.SecretKeySelector{}
if err = paveXP.GetValueInto(expXP, &sel); err != nil {
return errors.Wrapf(err, "cannot get SecretKeySelector from xp resource for fieldpath %q", expXP)
}
sensitive, err = client.GetSecretValue(ctx, sel)
if err != nil {
return err
}
expTF, err := expandedTFPath(expXP, mapping)
if err != nil {
return err
}
if err = paveTF.SetString(expTF, string(sensitive)); err != nil {
return errors.Wrapf(err, "cannot set string as terraform attribute for fieldpath %q", tf)
}
}
val, err := client.GetSecretValue(ctx, sel)
if err != nil {
return err
}
paveTF.SetString(k, string(val))
}

return nil
}

// GetSensitiveObservation will return sensitive information as terraform state
// attributes by reading them from connection details.
func GetSensitiveObservation(from runtime.Object, into map[string]interface{}, at map[string]string) error {
_, err := fieldpath.PaveObject(from)
func GetSensitiveObservation(from runtime.Object, into map[string]interface{}, mapping map[string]string) error {
pv, err := fieldpath.PaveObject(from)
if err != nil {
return err
}
xpParams := map[string]interface{}{}
if err = pv.GetValueInto("status.atProvider", &xpParams); err != nil {
return err
}
paveXP := fieldpath.Pave(xpParams)
paveTF := fieldpath.Pave(into)

var sensitive string
for tf, xp := range mapping {
expXPs, err := paveXP.ExpandWildcards(xp)
if err != nil {
return errors.Wrapf(err, "cannot expand wildcard for xp resource")
}
for _, expXP := range expXPs {
if sensitive, err = paveXP.GetString(expXP); err != nil {
return errors.Wrapf(err, "cannot get string from xp resource for fieldpath %q", expXP)
}
expTF, err := expandedTFPath(expXP, mapping)
if err != nil {
return err
}
if err = paveTF.SetString(expTF, sensitive); err != nil {
return errors.Wrapf(err, "cannot set string as terraform attribute for fieldpath %q", tf)
}
}
}
return nil
}

func expandedTFPath(expandedXP string, mapping map[string]string) (string, error) {
sExp, err := fieldpath.Parse(expandedXP)
if err != nil {
return "", err
}
tfWildcard := ""
for tf, xp := range mapping {
sxp, err := fieldpath.Parse(xp)
if err != nil {
return "", err
}
if segmentsMatches(sExp, sxp) {
tfWildcard = tf
break
}
}
if tfWildcard == "" {
return "", errors.Errorf("cannot find corresponding fieldpath mapping for %q", expandedXP)
}
sTF, err := fieldpath.Parse(tfWildcard)
if err != nil {
return "", err
}
for i, s := range sTF {
if s.Field == "*" {
sTF[i] = sExp[i]
}
}

return sTF.String(), nil
}

func segmentsMatches(a fieldpath.Segments, b fieldpath.Segments) bool {
if len(a) != len(b) {
return false
}
for i, s := range a {
sb := b[i]
if s.Field == "*" || sb.Field == "*" {
continue
}
if s.Type != sb.Type {
return false
}
if s.Field != sb.Field {
return false
}
if s.Index != sb.Index {
return false
}
}
return true
}
Loading

0 comments on commit 9e116bb

Please sign in to comment.