Skip to content

Commit

Permalink
Add utilities to generate EnvVars for secret (#1699)
Browse files Browse the repository at this point in the history
* Add utility to read file and directory from a pod

* Add copyright to new files

* Address review comments - fix error message and add comments

* Add Environment to PodOptions

* Add SecretMounts to PodOptions

* Add tests for new fields added to PodOptions

* Add function comment

* Revert file reader and SecretMounts implementation

* Remove stale test

* Add kopia repository storage args generation utilities

* Address review comments, add copyright to new files

* Address review comments - Update tests to use flags

* Use map[string][]byte instead of map[string]string

* Add utilities to generate EnvVars for secret

* Add test for ResolveS3Endpoint

* Set session token to env var as value

* Remove unused field

* Update test
  • Loading branch information
ankitjain235 committed Dec 2, 2022
1 parent f65bc3c commit ecb708d
Show file tree
Hide file tree
Showing 2 changed files with 215 additions and 0 deletions.
98 changes: 98 additions & 0 deletions pkg/kopia/command/storage/secret_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@

package storage

import (
"context"
"time"

"github.com/Azure/go-autorest/autorest/azure"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"

"github.com/kanisterio/kanister/pkg/aws"
"github.com/kanisterio/kanister/pkg/secrets"
)

type LocType string

const (
Expand All @@ -30,6 +42,11 @@ const (
LocTypeGCS LocType = "gcs"
LocTypeAzure LocType = "azure"
LocTypeFilestore LocType = "filestore"

// Azure location related environment variables
azureStorageAccountEnv = "AZURE_STORAGE_ACCOUNT"
azureStorageKeyEnv = "AZURE_STORAGE_KEY"
azureStorageDomainEnv = "AZURE_STORAGE_DOMAIN"
)

func getBucketNameFromMap(m map[string][]byte) string {
Expand Down Expand Up @@ -57,6 +74,87 @@ func locationType(m map[string][]byte) LocType {
return LocType(m[typeKey])
}

// GenerateEnvSpecFromCredentialSecret parses the secret and returns
// list of EnvVar based on secret type
func GenerateEnvSpecFromCredentialSecret(s *v1.Secret, assumeRoleDurationS3 time.Duration) ([]v1.EnvVar, error) {
if s == nil {
return nil, errors.New("Secret cannot be nil")
}
secType := string(s.Type)
switch secType {
case secrets.AWSSecretType:
return getEnvSpecForAWSCredentialSecret(s, assumeRoleDurationS3)
case secrets.AzureSecretType:
return getEnvSpecForAzureCredentialSecret(s)
}
// We only need to set the environment variables in cases where
// secret type is AWS or Azure.
return nil, nil
}

func getEnvSpecForAWSCredentialSecret(s *v1.Secret, assumeRoleDuration time.Duration) ([]v1.EnvVar, error) {
var err error
envVars := []v1.EnvVar{}
envVars = append(
envVars,
getEnvVarWithSecretRef(aws.AccessKeyID, s.Name, secrets.AWSAccessKeyID),
getEnvVarWithSecretRef(aws.SecretAccessKey, s.Name, secrets.AWSSecretAccessKey),
)
creds, err := secrets.ExtractAWSCredentials(context.Background(), s, assumeRoleDuration)
if err != nil {
return nil, err
}
if creds.SessionToken != "" {
envVars = append(envVars, getEnvVar(aws.SessionToken, creds.SessionToken))
}
return envVars, nil
}

func getEnvSpecForAzureCredentialSecret(s *v1.Secret) ([]v1.EnvVar, error) {
envVars := []v1.EnvVar{}
envVars = append(
envVars,
getEnvVarWithSecretRef(azureStorageAccountEnv, s.Name, secrets.AzureStorageAccountID),
getEnvVarWithSecretRef(azureStorageKeyEnv, s.Name, secrets.AzureStorageAccountKey),
)
azureSecret, err := secrets.ExtractAzureCredentials(s)
if err != nil {
return nil, err
}
storageEnv := azureSecret.EnvironmentName
if storageEnv != "" {
env, err := azure.EnvironmentFromName(storageEnv)
if err != nil {
return nil, errors.Wrapf(err, "Failed to get azure environment from name: %s", storageEnv)
}
blobDomain := "blob." + env.StorageEndpointSuffix
// TODO : Check how we can set this env to use value from secret
envVars = append(envVars, getEnvVar(azureStorageDomainEnv, blobDomain))
}
return envVars, nil
}

func getEnvVarWithSecretRef(varName, secretName, secretKey string) v1.EnvVar {
return v1.EnvVar{
Name: varName,
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
Key: secretKey,
LocalObjectReference: v1.LocalObjectReference{
Name: secretName,
},
},
},
}
}

func getEnvVar(varName, value string) v1.EnvVar {
return v1.EnvVar{
Name: varName,
Value: value,
}
}

// GetMapForLocationValues return a map with valid keys
// for different location values
func GetMapForLocationValues(
Expand Down
117 changes: 117 additions & 0 deletions pkg/kopia/command/storage/secret_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@ package storage

import (
"testing"
"time"

"gopkg.in/check.v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/kanisterio/kanister/pkg/aws"
"github.com/kanisterio/kanister/pkg/secrets"
)

func Test(t *testing.T) { check.TestingT(t) }
Expand Down Expand Up @@ -70,6 +76,117 @@ func (s *StorageUtilsSuite) TestLocationUtils(c *check.C) {
}
}

func (s *StorageUtilsSuite) TestGenerateEnvSpecFromCredentialSecret(c *check.C) {
awsAccessKeyId := "access-key-id"
awsSecretAccessKey := "secret-access-key"

azureStorageAccountID := "azure-storage-account-id"
azureStorageAccountKey := "azure-storage-account-key"
azureStorageEnvironment := "AZURECLOUD"

locSecretName := "test-secret"
for _, tc := range []struct {
secret *v1.Secret
expectedEnvVars []v1.EnvVar
check.Checker
}{
{
secret: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: locSecretName,
},
Type: v1.SecretType(secrets.AWSSecretType),
Data: map[string][]byte{
secrets.AWSAccessKeyID: []byte(awsAccessKeyId),
secrets.AWSSecretAccessKey: []byte(awsSecretAccessKey),
},
},
expectedEnvVars: []v1.EnvVar{
{
Name: aws.AccessKeyID,
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: locSecretName,
},
Key: secrets.AWSAccessKeyID,
},
},
},
{
Name: aws.SecretAccessKey,
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: locSecretName,
},
Key: secrets.AWSSecretAccessKey,
},
},
},
},
Checker: check.IsNil,
},
{
secret: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: locSecretName,
},
Type: v1.SecretType(secrets.AzureSecretType),
Data: map[string][]byte{
secrets.AzureStorageAccountID: []byte(azureStorageAccountID),
secrets.AzureStorageAccountKey: []byte(azureStorageAccountKey),
secrets.AzureStorageEnvironment: []byte(azureStorageEnvironment),
},
},
expectedEnvVars: []v1.EnvVar{
{
Name: azureStorageAccountEnv,
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: locSecretName,
},
Key: secrets.AzureStorageAccountID,
},
},
},
{
Name: azureStorageKeyEnv,
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: locSecretName,
},
Key: secrets.AzureStorageAccountKey,
},
},
},
{
Name: azureStorageDomainEnv,
Value: "blob.core.windows.net",
},
},
Checker: check.IsNil,
},
{
secret: nil,
Checker: check.NotNil,
},
{
secret: &v1.Secret{
Type: "Opaque",
},
Checker: check.IsNil,
expectedEnvVars: nil,
},
} {
envVars, err := GenerateEnvSpecFromCredentialSecret(tc.secret, time.Duration(0))
c.Assert(err, tc.Checker)
c.Assert(envVars, check.DeepEquals, tc.expectedEnvVars)
}
}

func (s *StorageUtilsSuite) TestGetMapForLocationValues(c *check.C) {
prefixValue := "test-prefix"
regionValue := "test-region"
Expand Down

0 comments on commit ecb708d

Please sign in to comment.