Skip to content

Commit

Permalink
rad credential show - support for IRSA (#7757)
Browse files Browse the repository at this point in the history
# Description

rad credential show should work with the new datamodel that supports 2
aws credential types - accesskey and irsa

## Type of change

- This pull request adds or changes features of Radius and has an
approved issue (issue link required).
Partially Fixes: #7618

---------

Signed-off-by: nithyatsu <[email protected]>
  • Loading branch information
nithyatsu authored Jul 30, 2024
1 parent c9b6581 commit 9b77737
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 23 deletions.
31 changes: 29 additions & 2 deletions pkg/cli/cmd/credential/show/objectformats.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func credentialFormatAzureWorkloadIdentity() output.FormatterOptions {
}
}

func credentialFormatAWS() output.FormatterOptions {
func credentialFormatAWSAccessKey() output.FormatterOptions {
return output.FormatterOptions{
Columns: []output.Column{
{
Expand All @@ -85,9 +85,36 @@ func credentialFormatAWS() output.FormatterOptions {
Heading: "REGISTERED",
JSONPath: "{ .Enabled }",
},
{
Heading: "KIND",
JSONPath: "{ .AWSCredentials.Kind }",
},
{
Heading: "ACCESSKEYID",
JSONPath: "{ .AWSCredentials.AccessKeyID }",
JSONPath: "{ .AWSCredentials.AccessKey.AccessKeyID }",
},
},
}
}

func credentialFormatAWSIRSA() output.FormatterOptions {
return output.FormatterOptions{
Columns: []output.Column{
{
Heading: "NAME",
JSONPath: "{ .Name }",
},
{
Heading: "REGISTERED",
JSONPath: "{ .Enabled }",
},
{
Heading: "KIND",
JSONPath: "{ .AWSCredentials.Kind }",
},
{
Heading: "ROLEARN",
JSONPath: "{ .AWSCredentials.IRSA.RoleARN }",
},
},
}
Expand Down
37 changes: 33 additions & 4 deletions pkg/cli/cmd/credential/show/objectformats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,52 @@ func Test_credentialFormat_Azure_WorkloadIdentity(t *testing.T) {
require.Equal(t, expected, buffer.String())
}

func Test_credentialFormat_AWS(t *testing.T) {
func Test_credentialFormatAWSAccessKey(t *testing.T) {
obj := credential.ProviderCredentialConfiguration{
CloudProviderStatus: credential.CloudProviderStatus{
Name: "test",
Enabled: true,
},
AWSCredentials: &credential.AWSCredentialProperties{
AccessKeyID: to.Ptr("test-access-key-id"),
Kind: to.Ptr("AccessKey"),
AccessKey: &credential.AWSAccessKeyCredentialProperties{
Kind: to.Ptr("AccessKey"),
AccessKeyID: to.Ptr("test-access-key-id"),
},
},
}

buffer := &bytes.Buffer{}
credentialFormatOutput := credentialFormatAWSAccessKey()

err := output.Write(output.FormatTable, obj, buffer, credentialFormatOutput)
require.NoError(t, err)

expected := "NAME REGISTERED KIND ACCESSKEYID\ntest true AccessKey test-access-key-id\n"
require.Equal(t, expected, buffer.String())
}

func Test_credentialFormatAWSIRSA(t *testing.T) {
obj := credential.ProviderCredentialConfiguration{
CloudProviderStatus: credential.CloudProviderStatus{
Name: "test",
Enabled: true,
},
AWSCredentials: &credential.AWSCredentialProperties{
Kind: to.Ptr("IRSA"),
IRSA: &credential.AWSIRSACredentialProperties{
Kind: to.Ptr("IRSA"),
RoleARN: to.Ptr("test-role-arn"),
},
},
}

buffer := &bytes.Buffer{}
credentialFormatOutput := credentialFormatAWS()
credentialFormatOutput := credentialFormatAWSIRSA()

err := output.Write(output.FormatTable, obj, buffer, credentialFormatOutput)
require.NoError(t, err)

expected := "NAME REGISTERED ACCESSKEYID\ntest true test-access-key-id\n"
expected := "NAME REGISTERED KIND ROLEARN\ntest true IRSA test-role-arn\n"
require.Equal(t, expected, buffer.String())
}
9 changes: 8 additions & 1 deletion pkg/cli/cmd/credential/show/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,14 @@ func (r *Runner) Run(ctx context.Context) error {
return fmt.Errorf("unknown Azure credential kind, expected ServicePrincipal or WorkloadIdentity (got %s)", *providers.AzureCredentials.Kind)
}
case "aws":
output = credentialFormatAWS()
switch *providers.AWSCredentials.Kind {
case datamodel.AWSAccessKeyCredentialKind:
output = credentialFormatAWSAccessKey()
case datamodel.AWSIRSACredentialKind:
output = credentialFormatAWSIRSA()
default:
return fmt.Errorf("unknown AWS credential kind, expected AccessKey or IRSA (got %s)", *providers.AWSCredentials.Kind)
}
default:
return fmt.Errorf("unknown credential type: %s", r.Kind)
}
Expand Down
5 changes: 4 additions & 1 deletion pkg/cli/cmd/credential/show/show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ func Test_Run(t *testing.T) {
Name: "aws",
Enabled: true,
},
AWSCredentials: &cli_credential.AWSCredentialProperties{
Kind: to.Ptr("AccessKey"),
},
}

client := cli_credential.NewMockCredentialManagementClient(ctrl)
Expand All @@ -205,7 +208,7 @@ func Test_Run(t *testing.T) {
err := runner.Run(context.Background())
require.NoError(t, err)

credentialFormatOutput := credentialFormatAWS()
credentialFormatOutput := credentialFormatAWSAccessKey()

expected := []any{
output.LogOutput{
Expand Down
81 changes: 66 additions & 15 deletions pkg/cli/credential/aws_credential_management.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,32 @@ const (
)

type AWSCredentialProperties struct {
// AccessKeyID is the access key ID for the AWS credential.
// Kind is the credential kind (AccessKey or IRSA)
Kind *string

// AccessKey is the properties for an AWS access key credential
AccessKey *AWSAccessKeyCredentialProperties

// IRSA is the properties for an AWS IRSA credential
IRSA *AWSIRSACredentialProperties
}

type AWSAccessKeyCredentialProperties struct {
// Kind is the credential kind (Must be AccessKey)
Kind *string

// AccessKeyID is the AWS access key ID
AccessKeyID *string
}

type AWSIRSACredentialProperties struct {
// Kind is the credential kind (Must be IRSA)
Kind *string

// RoleARN is the AWS IRSA role ARN
RoleARN *string
}

// AWSCredentialManagementClient is used to interface with cloud provider configuration and credentials.
type AWSCredentialManagementClientInterface interface {
// Get gets the credential registered with the given ucp provider plane.
Expand Down Expand Up @@ -77,28 +99,57 @@ func (cpm *AWSCredentialManagementClient) Put(ctx context.Context, credential uc
// "Get" retrieves the credentials for the specified cloud provider from the backend and returns a ProviderCredentialConfiguration
// object containing the credentials or an error if the credentials could not be retrieved.
func (cpm *AWSCredentialManagementClient) Get(ctx context.Context, credentialName string) (ProviderCredentialConfiguration, error) {
var err error

// We send only the name when getting credentials from backend which we already have access to
resp, err := cpm.AWSCredentialClient.Get(ctx, AWSPlaneName, credentialName, nil)
if err != nil {
return ProviderCredentialConfiguration{}, err
}
awsAccessKeyCredentials, ok := resp.AwsCredentialResource.Properties.(*ucp.AwsAccessKeyCredentialProperties)
if !ok {

switch *resp.AwsCredentialResource.Properties.GetAwsCredentialProperties().Kind {
case ucp.AWSCredentialKindAccessKey:
awsAccessKeyCredentials, ok := resp.AwsCredentialResource.Properties.(*ucp.AwsAccessKeyCredentialProperties)
if !ok {
return ProviderCredentialConfiguration{}, clierrors.Message("Unable to find credentials for cloud provider %s.", AWSCredential)
}

providerCredentialConfiguration := ProviderCredentialConfiguration{
CloudProviderStatus: CloudProviderStatus{
Name: AWSCredential,
Enabled: true,
},
AWSCredentials: &AWSCredentialProperties{
Kind: (*string)(awsAccessKeyCredentials.Kind),
AccessKey: &AWSAccessKeyCredentialProperties{
AccessKeyID: awsAccessKeyCredentials.AccessKeyID,
},
},
}
return providerCredentialConfiguration, nil
case ucp.AWSCredentialKindIRSA:
awsIRSACredentials, ok := resp.AwsCredentialResource.Properties.(*ucp.AwsIRSACredentialProperties)
if !ok {
return ProviderCredentialConfiguration{}, clierrors.Message("Unable to find credentials for cloud provider %s.", AWSCredential)
}

providerCredentialConfiguration := ProviderCredentialConfiguration{
CloudProviderStatus: CloudProviderStatus{
Name: AWSCredential,
Enabled: true,
},
AWSCredentials: &AWSCredentialProperties{
Kind: (*string)(awsIRSACredentials.Kind),
IRSA: &AWSIRSACredentialProperties{
RoleARN: awsIRSACredentials.RoleARN,
},
},
}
return providerCredentialConfiguration, nil

default:
return ProviderCredentialConfiguration{}, clierrors.Message("Unable to find credentials for cloud provider %s.", AWSCredential)
}

providerCredentialConfiguration := ProviderCredentialConfiguration{
CloudProviderStatus: CloudProviderStatus{
Name: AWSCredential,
Enabled: true,
},
AWSCredentials: &AWSCredentialProperties{
AccessKeyID: awsAccessKeyCredentials.AccessKeyID,
},
}
return providerCredentialConfiguration, nil

}

// List, lists the AWS credentials registered
Expand Down

0 comments on commit 9b77737

Please sign in to comment.