Skip to content
This repository was archived by the owner on Nov 20, 2024. It is now read-only.

Commit c1600dc

Browse files
committed
Support namespaced Secret
1 parent 0d17251 commit c1600dc

File tree

6 files changed

+54
-26
lines changed

6 files changed

+54
-26
lines changed

api/v1alpha1/workspace_types.go

+3
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ type WorkspaceSpec struct {
123123
RunTriggers []*RunTrigger `json:"runTriggers,omitempty"`
124124
// File path within operator pod to load workspace secrets
125125
SecretsMountPath string `json:"secretsMountPath"`
126+
// Name of the secret in the same namespace as the Workspace CR that contains workspace secrets. Those secrets are merged with secrets in the secretsMountPath.
127+
// +optional
128+
SecretName string `json:"secretName"`
126129
// SSH Key ID. This key must already exist in the TF Cloud organization. This can either be the user assigned name of the SSH Key, or the system assigned ID.
127130
// +optional
128131
SSHKeyID string `json:"sshKeyID,omitempty"`

config/crd/bases/app.terraform.io_workspaces.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ spec:
140140
- sourceableName
141141
type: object
142142
type: array
143+
secretName:
144+
description: Name of the secret in the same namespace as the Workspace
145+
CR that contains workspace secrets. Those secrets are merged with
146+
secrets in the secretsMountPath.
147+
type: string
143148
secretsMountPath:
144149
description: File path within operator pod to load workspace secrets
145150
type: string

workspacehelper/k8s_secret.go

+8
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,22 @@ import (
1111

1212
// GetSecretData retrieves the data from a secret in a given namespace
1313
func (r *WorkspaceHelper) GetSecretData(namespace string, name string) (map[string][]byte, error) {
14+
// If no secretName defined, return empty map
15+
if name == "" {
16+
return make(map[string][]byte), nil
17+
}
18+
1419
r.reqLogger.Info("Getting Secret", "Namespace", namespace, "Name", name)
1520

1621
secret := &corev1.Secret{}
1722
err := r.client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, secret)
23+
1824
if err != nil {
1925
r.reqLogger.Error(err, "Failed to get Secret", "Namespace", namespace, "Name", name)
26+
2027
return nil, err
2128
}
29+
2230
return secret.Data, nil
2331
}
2432

workspacehelper/tfc_variable.go

+25-22
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ func (t *TerraformCloudClient) deleteVariablesFromTFC(specTFCVariables []*tfc.Va
5959
return nil
6060
}
6161

62-
func (t *TerraformCloudClient) createVariablesOnTFC(workspace *tfc.Workspace, specTFCVariables []*tfc.Variable, workspaceVariables []*tfc.Variable) (bool, error) {
62+
func (t *TerraformCloudClient) createVariablesOnTFC(workspace *tfc.Workspace, specTFCVariables []*tfc.Variable, workspaceVariables []*tfc.Variable, secretData map[string][]byte) (bool, error) {
6363
updated := false
6464
for _, v := range specTFCVariables {
6565
index := find(workspaceVariables, v.Key)
6666
if index < 0 {
67-
err := t.CreateTerraformVariable(workspace, v)
67+
err := t.CreateTerraformVariable(workspace, v, secretData)
6868
if err != nil {
6969
return false, err
7070
}
@@ -104,15 +104,15 @@ func getNonSensitiveVariablesToUpdate(specTFCVariables []*tfc.Variable, workspac
104104
return variablesToUpdate
105105
}
106106

107-
func getSensitiveVariablesToUpdate(specTFCVariables []*tfc.Variable, workspaceVariables []*tfc.Variable, secretsMountPath string) ([]*tfc.Variable, error) {
107+
func getSensitiveVariablesToUpdate(specTFCVariables []*tfc.Variable, workspaceVariables []*tfc.Variable, secretsMountPath string, secretData map[string][]byte) ([]*tfc.Variable, error) {
108108
variablesToUpdate := []*tfc.Variable{}
109109
for _, v := range specTFCVariables {
110110
index := find(workspaceVariables, v.Key)
111111
if index < 0 {
112112
continue
113113
}
114114
if workspaceVariables[index].Sensitive {
115-
if err := checkAndRetrieveIfSensitive(v, secretsMountPath); err != nil {
115+
if err := checkAndRetrieveIfSensitive(v, secretsMountPath, secretData); err != nil {
116116
return nil, err
117117
}
118118
v.ID = workspaceVariables[index].ID
@@ -124,15 +124,15 @@ func getSensitiveVariablesToUpdate(specTFCVariables []*tfc.Variable, workspaceVa
124124
return variablesToUpdate, nil
125125
}
126126

127-
func generateUpdateVariableList(specTFCVariables []*tfc.Variable, workspaceVariables []*tfc.Variable, secretsMountPath string) ([]*tfc.Variable, error) {
127+
func generateUpdateVariableList(specTFCVariables []*tfc.Variable, workspaceVariables []*tfc.Variable, secretsMountPath string, secretData map[string][]byte) ([]*tfc.Variable, error) {
128128
updateList := []*tfc.Variable{}
129129

130130
nonSensitiveVariablesToUpdate := getNonSensitiveVariablesToUpdate(specTFCVariables, workspaceVariables)
131131
if len(nonSensitiveVariablesToUpdate) == 0 {
132132
return updateList, nil
133133
}
134134

135-
sensitiveVariablesToUpdate, err := getSensitiveVariablesToUpdate(specTFCVariables, workspaceVariables, secretsMountPath)
135+
sensitiveVariablesToUpdate, err := getSensitiveVariablesToUpdate(specTFCVariables, workspaceVariables, secretsMountPath, secretData)
136136
if err != nil {
137137
return nonSensitiveVariablesToUpdate, err
138138
}
@@ -143,7 +143,7 @@ func generateUpdateVariableList(specTFCVariables []*tfc.Variable, workspaceVaria
143143
}
144144

145145
// CheckVariables creates, updates, or deletes variables as needed
146-
func (t *TerraformCloudClient) CheckVariables(workspace string, specTFCVariables []*tfc.Variable) (bool, error) {
146+
func (t *TerraformCloudClient) CheckVariables(workspace string, specTFCVariables []*tfc.Variable, secretData map[string][]byte) (bool, error) {
147147
tfcWorkspace, err := t.Client.Workspaces.Read(context.TODO(), t.Organization, workspace)
148148
if err != nil {
149149
return false, err
@@ -156,12 +156,12 @@ func (t *TerraformCloudClient) CheckVariables(workspace string, specTFCVariables
156156
return false, err
157157
}
158158

159-
createdVariables, err := t.createVariablesOnTFC(tfcWorkspace, specTFCVariables, workspaceVariables)
159+
createdVariables, err := t.createVariablesOnTFC(tfcWorkspace, specTFCVariables, workspaceVariables, secretData)
160160
if err != nil {
161161
return false, err
162162
}
163163

164-
variablesToUpdate, err := generateUpdateVariableList(specTFCVariables, workspaceVariables, t.SecretsMountPath)
164+
variablesToUpdate, err := generateUpdateVariableList(specTFCVariables, workspaceVariables, t.SecretsMountPath, secretData)
165165
if err != nil || len(variablesToUpdate) == 0 {
166166
return false, err
167167
}
@@ -222,25 +222,28 @@ func (t *TerraformCloudClient) UpdateTerraformVariables(variables []*tfc.Variabl
222222
return nil
223223
}
224224

225-
func checkAndRetrieveIfSensitive(variable *tfc.Variable, secretsMountPath string) error {
226-
// Try to read variables with empty value from file. If the value isn't empty,
227-
// it was already read fromValue.SecretKeyRef.
228-
if variable.Sensitive && variable.Value == "" {
229-
filePath := fmt.Sprintf("%s/%s", secretsMountPath, variable.Key)
230-
231-
data, err := ioutil.ReadFile(filePath)
232-
if err != nil {
233-
return fmt.Errorf("could not get secret, %s", err)
225+
func checkAndRetrieveIfSensitive(variable *tfc.Variable, secretsMountPath string, secretData map[string][]byte) error {
226+
if variable.Sensitive {
227+
// First check if the key is in the namespaced Secret
228+
if val, ok := secretData[variable.Key]; ok {
229+
variable.Value = string(val)
230+
} else {
231+
// Try to find key in the mounted Secret
232+
filePath := fmt.Sprintf("%s/%s", secretsMountPath, variable.Key)
233+
data, err := ioutil.ReadFile(filePath)
234+
if err != nil {
235+
return fmt.Errorf("could not get secret, %s", err)
236+
}
237+
secret := string(data)
238+
variable.Value = secret
234239
}
235-
secret := string(data)
236-
variable.Value = secret
237240
}
238241
return nil
239242
}
240243

241244
// CreateTerraformVariable creates a Terraform variable based on key and value
242-
func (t *TerraformCloudClient) CreateTerraformVariable(workspace *tfc.Workspace, variable *tfc.Variable) error {
243-
if err := checkAndRetrieveIfSensitive(variable, t.SecretsMountPath); err != nil {
245+
func (t *TerraformCloudClient) CreateTerraformVariable(workspace *tfc.Workspace, variable *tfc.Variable, secretData map[string][]byte) error {
246+
if err := checkAndRetrieveIfSensitive(variable, t.SecretsMountPath, secretData); err != nil {
244247
return err
245248
}
246249
options := tfc.VariableCreateOptions{

workspacehelper/tfc_variable_test.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ func TestShouldGetSensitiveVariablesForUpdate(t *testing.T) {
9999
Sensitive: true,
100100
},
101101
}
102-
update, err := getSensitiveVariablesToUpdate(specVariables, workspaceVariables, secretsMount)
102+
secretData := make(map[string][]byte)
103+
update, err := getSensitiveVariablesToUpdate(specVariables, workspaceVariables, secretsMount, secretData)
103104
assert.NoError(t, err)
104105
assert.Len(t, update, 1)
105106
assert.Equal(t, update[0].Key, specVariables[0].Key)
@@ -132,7 +133,8 @@ func TestShouldUpdateVariables(t *testing.T) {
132133
HCL: false,
133134
},
134135
}
135-
update, err := generateUpdateVariableList(specVariables, workspaceVariables, secretsMount)
136+
secretData := make(map[string][]byte)
137+
update, err := generateUpdateVariableList(specVariables, workspaceVariables, secretsMount, secretData)
136138
assert.NoError(t, err)
137139
assert.Len(t, update, 2)
138140
assert.False(t, update[0].Sensitive)
@@ -171,7 +173,8 @@ func TestShouldNotUpdateVariables(t *testing.T) {
171173
HCL: true,
172174
},
173175
}
174-
update, err := generateUpdateVariableList(specVariables, workspaceVariables, secretsMount)
176+
secretData := make(map[string][]byte)
177+
update, err := generateUpdateVariableList(specVariables, workspaceVariables, secretsMount, secretData)
175178
assert.NoError(t, err)
176179
assert.Len(t, update, 0)
177180
}

workspacehelper/workspace_helper.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,14 @@ func (r *WorkspaceHelper) updateVariables(instance *appv1alpha1.Workspace) (bool
299299
}
300300
}
301301

302+
secretData, err := r.GetSecretData(instance.Namespace, instance.Spec.SecretName)
303+
if err != nil {
304+
r.reqLogger.Error(err, "Could not get namespaced Secret data")
305+
return false, err
306+
}
307+
302308
specTFCVariables := MapToTFCVariable(instance.Spec.Variables)
303-
updatedVariables, err := r.tfclient.CheckVariables(workspace, specTFCVariables)
309+
updatedVariables, err := r.tfclient.CheckVariables(workspace, specTFCVariables, secretData)
304310
if err != nil {
305311
r.reqLogger.Error(err, "Could not update variables")
306312
return false, err

0 commit comments

Comments
 (0)