Skip to content

fix: codefresh_context disable decrypt when forbidDecrypt feature flag is set #156

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

Merged
merged 8 commits into from
Dec 17, 2024
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions codefresh/cfclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import (

// Client token, host, htpp.Client
type Client struct {
Token string
TokenHeader string
Host string
HostV2 string
Client *http.Client
Token string
TokenHeader string
Host string
HostV2 string
featureFlags map[string]bool
Client *http.Client
}

// RequestOptions path, method, etc
Expand All @@ -35,11 +36,12 @@ func NewClient(hostname string, hostnameV2 string, token string, tokenHeader str
tokenHeader = "Authorization"
}
return &Client{
Host: hostname,
HostV2: hostnameV2,
Token: token,
TokenHeader: tokenHeader,
Client: &http.Client{},
Host: hostname,
HostV2: hostnameV2,
Token: token,
TokenHeader: tokenHeader,
Client: &http.Client{},
featureFlags: map[string]bool{},
}

}
Expand Down Expand Up @@ -112,6 +114,25 @@ func (client *Client) RequestApiXAccessToken(opt *RequestOptions) ([]byte, error
return body, nil
}

func (client *Client) isFeatureFlagEnabled(flagName string) (bool, error) {

if len(client.featureFlags) == 0 {
currAcc, err := client.GetCurrentAccount()

if err != nil {
return false, err
}

client.featureFlags = currAcc.FeatureFlags
}

if val, ok := client.featureFlags[flagName]; ok {
return val, nil
}

return false, nil
}

// ToQS add extra parameters to path
func ToQS(qs map[string]string) string {
var arr = []string{}
Expand Down
40 changes: 35 additions & 5 deletions codefresh/cfclient/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@ import (
"fmt"
"log"
"net/url"

"golang.org/x/exp/slices"
)

var encryptedContextTypes = []string{
"secret",
"secret-yaml",
"storage.s3",
"storage.azuref",
}

type ContextErrorResponse struct {
Status int `json:"status,omitempty"`
Message string `json:"message,omitempty"`
Expand All @@ -17,9 +26,10 @@ type ContextMetadata struct {
}

type Context struct {
Metadata ContextMetadata `json:"metadata,omitempty"`
Spec ContextSpec `json:"spec,omitempty"`
Version string `json:"version,omitempty"`
Metadata ContextMetadata `json:"metadata,omitempty"`
Spec ContextSpec `json:"spec,omitempty"`
Version string `json:"version,omitempty"`
IsEncrypred bool `json:"isEncrypted,omitempty"`
}

type ContextSpec struct {
Expand All @@ -32,7 +42,18 @@ func (context *Context) GetID() string {
}

func (client *Client) GetContext(name string) (*Context, error) {
fullPath := fmt.Sprintf("/contexts/%s?decrypt=true", url.PathEscape(name))
fullPath := fmt.Sprintf("/contexts/%s", url.PathEscape(name))

forbidDecrypt, err := client.isFeatureFlagEnabled("forbidDecrypt")

if err != nil {
forbidDecrypt = false
}

if !forbidDecrypt {
fullPath += "?decrypt=true"
}

opts := RequestOptions{
Path: fullPath,
Method: "GET",
Expand All @@ -49,8 +70,17 @@ func (client *Client) GetContext(name string) (*Context, error) {
return nil, err
}

return &respContext, nil
// This is so not to break existing behavior while adding support for forbidDecrypt feature flag
// The provider used to always decrypt the contexts, hence we treat all contexts as decrypted unless forbidDecrypt is set
isEncryptedType := slices.Contains(encryptedContextTypes, respContext.Spec.Type)

respContext.IsEncrypred = false

if forbidDecrypt && isEncryptedType {
respContext.IsEncrypred = true
}

return &respContext, nil
}

func (client *Client) CreateContext(context *Context) (*Context, error) {
Expand Down
21 changes: 14 additions & 7 deletions codefresh/cfclient/current_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ type CurrentAccountUser struct {

// CurrentAccount spec
type CurrentAccount struct {
ID string
Name string
Users []CurrentAccountUser
Admins []CurrentAccountUser
ID string
Name string
Users []CurrentAccountUser
Admins []CurrentAccountUser
FeatureFlags map[string]bool
}

// GetCurrentAccount -
Expand All @@ -46,9 +47,10 @@ func (client *Client) GetCurrentAccount() (*CurrentAccount, error) {
return nil, fmt.Errorf("GetCurrentAccount - cannot get activeAccountName")
}
currentAccount := &CurrentAccount{
Name: activeAccountName,
Users: make([]CurrentAccountUser, 0),
Admins: make([]CurrentAccountUser, 0),
Name: activeAccountName,
Users: make([]CurrentAccountUser, 0),
Admins: make([]CurrentAccountUser, 0),
FeatureFlags: make(map[string]bool),
}

accountAdminsIDs := make([]string, 0)
Expand All @@ -62,6 +64,11 @@ func (client *Client) GetCurrentAccount() (*CurrentAccount, error) {
for _, adminI := range admins {
accountAdminsIDs = append(accountAdminsIDs, adminI.(string))
}
featureFlags := accX.Get("features").ObjxMap()

for k, v := range featureFlags {
currentAccount.FeatureFlags[k] = v.(bool)
}
break
}
}
Expand Down
2 changes: 1 addition & 1 deletion codefresh/context/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func flattenStorageContextConfig(spec cfclient.ContextSpec, auth map[string]inte
func FlattenJsonConfigStorageContextConfig(spec cfclient.ContextSpec) []interface{} {
auth := make(map[string]interface{})
auth["json_config"] = spec.Data["auth"].(map[string]interface{})["jsonConfig"]
auth["type"] = spec.Data["type"]
auth["type"] = spec.Data["auth"].(map[string]interface{})["type"]
return flattenStorageContextConfig(spec, auth)
}

Expand Down
2 changes: 1 addition & 1 deletion codefresh/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

"github.com/codefresh-io/terraform-provider-codefresh/codefresh/cfclient"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"os"
)

Expand Down Expand Up @@ -87,5 +86,6 @@ func configureProvider(d *schema.ResourceData) (interface{}, error) {
if token == "" {
token = os.Getenv(ENV_CODEFRESH_API_KEY)
}

return cfclient.NewClient(apiURL, apiURLV2, token, ""), nil
}
17 changes: 12 additions & 5 deletions codefresh/resource_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,14 @@ func resourceContextRead(d *schema.ResourceData, meta interface{}) error {
}

context, err := client.GetContext(contextName)

if err != nil {
log.Printf("[DEBUG] Error while getting context. Error = %v", contextName)
return err
}

err = mapContextToResource(*context, d)

if err != nil {
log.Printf("[DEBUG] Error while mapping context to resource. Error = %v", err)
return err
Expand Down Expand Up @@ -225,14 +227,20 @@ func resourceContextDelete(d *schema.ResourceData, meta interface{}) error {
func mapContextToResource(context cfclient.Context, d *schema.ResourceData) error {

err := d.Set("name", context.Metadata.Name)

if err != nil {
return err
}

err = d.Set("spec", flattenContextSpec(context.Spec))
if err != nil {
log.Printf("[DEBUG] Failed to flatten Context spec = %v", context.Spec)
return err
// Read spec from API if context is not encrypted or forbitDecrypt is not set
if !context.IsEncrypred {

err = d.Set("spec", flattenContextSpec(context.Spec))

if err != nil {
log.Printf("[DEBUG] Failed to flatten Context spec = %v", context.Spec)
return err
}
}

return nil
Expand All @@ -253,7 +261,6 @@ func flattenContextSpec(spec cfclient.ContextSpec) []interface{} {
case contextAzureStorage:
m[schemautil.MustNormalizeFieldName(currentContextType)] = storageContext.FlattenAzureStorageContextConfig(spec)
default:
log.Printf("[DEBUG] Invalid context type = %v", currentContextType)
return nil
}

Expand Down
4 changes: 2 additions & 2 deletions codefresh/resource_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ resource "codefresh_context" "test" {

spec {
config {
data = {
data = {
%q = %q
%q = %q
}
Expand All @@ -223,7 +223,7 @@ resource "codefresh_context" "test" {

spec {
secret {
data = {
data = {
%q = %q
%q = %q
}
Expand Down
77 changes: 77 additions & 0 deletions docs/resources/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ YAML
```hcl
resource "codefresh_context" "test-secret-yaml" {
name = "my-shared-secret-yaml"
decrypt_spec = false
spec {
# NOTE: The `-` from secret-yaml is stripped because the character is not allowed in Field name
# File passed MUST be a valid YAML
Expand All @@ -96,6 +97,82 @@ resource "codefresh_context" "test-secret-yaml" {
}
```

#### AWS S3 storage context

```hcl
resource "codefresh_context" "test-s3" {
name = "my-s3-context"

decrypt_spec = false

spec {
storages3 {
data {
auth {
type = "basic"
json_config = {accessKeyId = "key", secretAccessKey = "secret"}
}
}
}
}
}
```

#### Azure file storage context

```hcl
resource "codefresh_context" "test-azure" {
name = "my-azure-file-context"

decrypt_spec = false

spec {
storageazuref {
data {
auth {
type = "basic"
account_name = "account"
account_key = "key"
}
}
}
}
}
```

#### Google cloud storage context

```hcl
resource "codefresh_context" "test-google-cloud-storage" {
name = "my-gcs-context"

spec {
storagegc {
data {
auth {
type = "basic"
json_config = jsondecode(<<EOF
{
"type": "service_account",
"project_id": "PROJECT_ID",
"private_key_id": "KEY_ID",
"private_key": "-----BEGIN PRIVATE KEY-----\nPRIVATE_KEY\n-----END PRIVATE KEY-----\n",
"client_email": "SERVICE_ACCOUNT_EMAIL",
"client_id": "CLIENT_ID",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/SERVICE_ACCOUNT_EMAIL"
}
EOF
)
}
}
}
}
}
```

<!-- schema generated by tfplugindocs -->
## Schema

Expand Down
Loading
Loading