Skip to content

Commit

Permalink
Changes to support Secret Credential type for azure (#1275)
Browse files Browse the repository at this point in the history
* Initial changes to support Secret Credential type for azure

* update comments

* update stow

* Updated stow and added UTs

* remove comments

* remove trailing white space

* after reviews

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
bathina2 and mergify[bot] authored Mar 24, 2022
1 parent e49103b commit ac4bbb7
Show file tree
Hide file tree
Showing 16 changed files with 771 additions and 68 deletions.
74 changes: 54 additions & 20 deletions pkg/kanctl/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,8 @@ const (
gcpServiceKeyFlag = "service-key"
AzureStorageAccountFlag = "storage-account"
AzureStorageKeyFlag = "storage-key"
AzureStorageEnvFlag = "storage-env"

idField = secrets.AWSAccessKeyID
secretField = secrets.AWSSecretAccessKey
roleField = secrets.ConfigRole // required only for AWS IAM role
skipSSLVerifyFlag = "skip-SSL-verification"

schemaValidation = "Validate Profile schema"
Expand Down Expand Up @@ -142,6 +140,7 @@ func newAzureProfileCmd() *cobra.Command {

cmd.Flags().StringP(AzureStorageAccountFlag, "a", "", "Storage account name of the azure storage")
cmd.Flags().StringP(AzureStorageKeyFlag, "s", "", "Storage account key of the azure storage")
cmd.Flags().StringP(AzureStorageEnvFlag, "e", "", "The Azure cloud environment")

_ = cmd.MarkFlagRequired(AzureStorageAccountFlag)
_ = cmd.MarkFlagRequired(AzureStorageKeyFlag)
Expand All @@ -168,7 +167,7 @@ func createNewProfile(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
profile := constructProfile(lP, secret, string(secret.StringData[roleField]))
profile := constructProfile(lP, secret)
if dryRun {
// Just perform schema validation and print YAML
if err := validate.ProfileSchema(profile); err != nil {
Expand Down Expand Up @@ -234,26 +233,59 @@ func getLocationParams(cmd *cobra.Command) (*locationParams, error) {
}, nil
}

func constructProfile(lP *locationParams, secret *v1.Secret, role string) *v1alpha1.Profile {
func constructProfile(lP *locationParams, secret *v1.Secret) *v1alpha1.Profile {
var creds v1alpha1.Credential
if role == "" {
switch {
case lP.locationType == v1alpha1.LocationTypeS3Compliant && string(secret.StringData[secrets.ConfigRole]) != "": // aws case with role
creds = v1alpha1.Credential{
Type: v1alpha1.CredentialTypeSecret,
Secret: &v1alpha1.ObjectReference{
Name: secret.GetName(),
Namespace: secret.GetNamespace(),
},
}
case lP.locationType == v1alpha1.LocationTypeAzure && string(secret.StringData[secrets.AzureStorageEnvironment]) != "": // azure case with env
creds = v1alpha1.Credential{
Type: v1alpha1.CredentialTypeSecret,
Secret: &v1alpha1.ObjectReference{
Name: secret.GetName(),
Namespace: secret.GetNamespace(),
},
}
case lP.locationType == v1alpha1.LocationTypeAzure && string(secret.StringData[secrets.AzureStorageEnvironment]) == "": // azure case without env (type keypair)
creds = v1alpha1.Credential{
Type: v1alpha1.CredentialTypeKeyPair,
KeyPair: &v1alpha1.KeyPair{
IDField: idField,
SecretField: secretField,
IDField: secrets.AzureStorageAccountID,
SecretField: secrets.AzureStorageAccountKey,
Secret: v1alpha1.ObjectReference{
Name: secret.GetName(),
Namespace: secret.GetNamespace(),
},
},
}
} else {
case lP.locationType == v1alpha1.LocationTypeGCS: //GCP
creds = v1alpha1.Credential{
Type: v1alpha1.CredentialTypeSecret,
Secret: &v1alpha1.ObjectReference{
Name: secret.GetName(),
Namespace: secret.GetNamespace(),
Type: v1alpha1.CredentialTypeKeyPair,
KeyPair: &v1alpha1.KeyPair{
IDField: secrets.GCPProjectID,
SecretField: secrets.GCPServiceKey,
Secret: v1alpha1.ObjectReference{
Name: secret.GetName(),
Namespace: secret.GetNamespace(),
},
},
}
default: // All others fall into the AWS key pair format
creds = v1alpha1.Credential{
Type: v1alpha1.CredentialTypeKeyPair,
KeyPair: &v1alpha1.KeyPair{
IDField: secrets.AWSAccessKeyID,
SecretField: secrets.AWSSecretAccessKey,
Secret: v1alpha1.ObjectReference{
Name: secret.GetName(),
Namespace: secret.GetNamespace(),
},
},
}
}
Expand Down Expand Up @@ -283,9 +315,9 @@ func constructSecret(ctx context.Context, lP *locationParams, cmd *cobra.Command
accessKey, _ := cmd.Flags().GetString(awsAccessKeyFlag)
secretKey, _ := cmd.Flags().GetString(awsSecretKeyFlag)
roleKey, _ = cmd.Flags().GetString(awsRoleFlag)
data[idField] = accessKey
data[secretField] = secretKey
data[roleField] = roleKey
data[secrets.AWSAccessKeyID] = accessKey
data[secrets.AWSSecretAccessKey] = secretKey
data[secrets.ConfigRole] = roleKey
secretname = "s3"
case v1alpha1.LocationTypeGCS:
projectID, _ := cmd.Flags().GetString(gcpProjectIDFlag)
Expand All @@ -294,14 +326,16 @@ func constructSecret(ctx context.Context, lP *locationParams, cmd *cobra.Command
if err != nil {
return nil, err
}
data[idField] = projectID
data[secretField] = serviceKey
data[secrets.GCPProjectID] = projectID
data[secrets.GCPServiceKey] = serviceKey
secretname = "gcp"
case v1alpha1.LocationTypeAzure:
storageAccount, _ := cmd.Flags().GetString(AzureStorageAccountFlag)
storageKey, _ := cmd.Flags().GetString(AzureStorageKeyFlag)
data[idField] = storageAccount
data[secretField] = storageKey
storageEnv, _ := cmd.Flags().GetString(AzureStorageEnvFlag)
data[secrets.AzureStorageAccountID] = storageAccount
data[secrets.AzureStorageAccountKey] = storageKey
data[secrets.AzureStorageEnvironment] = storageEnv
secretname = "azure"
}
secret := &v1.Secret{
Expand Down
103 changes: 103 additions & 0 deletions pkg/kanctl/profile_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package kanctl

import (
"github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1"
"github.com/kanisterio/kanister/pkg/secrets"
check "gopkg.in/check.v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func (k *KanctlTestSuite) TestConstructProfile(c *check.C) {
for _, tc := range []struct {
lp *locationParams
secret *v1.Secret
retCredType v1alpha1.CredentialType
}{
{
lp: &locationParams{
locationType: v1alpha1.LocationTypeS3Compliant,
},
secret: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "sec",
Namespace: "ns",
},
StringData: map[string]string{
secrets.ConfigRole: "role",
},
},
retCredType: v1alpha1.CredentialTypeSecret,
},
{
lp: &locationParams{
locationType: v1alpha1.LocationTypeAzure,
},
secret: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "sec",
Namespace: "ns",
},
StringData: map[string]string{
secrets.AzureStorageEnvironment: "env",
},
},
retCredType: v1alpha1.CredentialTypeSecret,
},
{
lp: &locationParams{
locationType: v1alpha1.LocationTypeAzure,
},
secret: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "sec",
Namespace: "ns",
},
StringData: map[string]string{
secrets.AzureStorageEnvironment: "",
},
},
retCredType: v1alpha1.CredentialTypeKeyPair,
},
{
lp: &locationParams{
locationType: v1alpha1.LocationTypeAzure,
},
secret: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "sec",
Namespace: "ns",
},
StringData: map[string]string{},
},
retCredType: v1alpha1.CredentialTypeKeyPair,
},
{
lp: &locationParams{
locationType: v1alpha1.LocationTypeGCS,
},
secret: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "sec",
Namespace: "ns",
},
},
retCredType: v1alpha1.CredentialTypeKeyPair,
},
{
lp: &locationParams{
locationType: v1alpha1.LocationTypeS3Compliant,
},
secret: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "sec",
Namespace: "ns",
},
},
retCredType: v1alpha1.CredentialTypeKeyPair,
},
} {
prof := constructProfile(tc.lp, tc.secret)
c.Assert(prof.Credential.Type, check.Equals, tc.retCredType)
}
}
27 changes: 22 additions & 5 deletions pkg/location/location.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,17 +207,34 @@ func getOSSecret(ctx context.Context, pType objectstore.ProviderType, cred param
ServiceKey: cred.KeyPair.Secret,
}
case objectstore.ProviderTypeAzure:
secret.Type = objectstore.SecretTypeAzStorageAccount
secret.Azure = &objectstore.SecretAzure{
StorageAccount: cred.KeyPair.ID,
StorageKey: cred.KeyPair.Secret,
}
return getAzureSecret(cred)
default:
return nil, errors.Errorf("unknown or unsupported provider type '%s'", pType)
}
return secret, nil
}

func getAzureSecret(cred param.Credential) (*objectstore.Secret, error) {
os := &objectstore.Secret{
Type: objectstore.SecretTypeAzStorageAccount,
}
switch cred.Type {
case param.CredentialTypeKeyPair:
os.Azure = &objectstore.SecretAzure{
StorageAccount: cred.KeyPair.ID,
StorageKey: cred.KeyPair.Secret,
}

case param.CredentialTypeSecret:
azSecret, err := secrets.ExtractAzureCredentials(cred.Secret)
if err != nil {
return nil, errors.Wrap(err, "Failed to extract azure credentials")
}
os.Azure = azSecret
}
return os, nil
}

func getAWSSecret(ctx context.Context, cred param.Credential) (*objectstore.Secret, error) {
os := &objectstore.Secret{
Type: objectstore.SecretTypeAwsAccessKey,
Expand Down
Loading

0 comments on commit ac4bbb7

Please sign in to comment.