From 6e6026f8e97b5a91f04ae0b58728ecbfd8242985 Mon Sep 17 00:00:00 2001 From: kkb0318 Date: Wed, 17 Apr 2024 21:47:47 +0900 Subject: [PATCH] delete IdP --- internal/client/aws.go | 55 ++++++++++++++++--- .../controller/irsasetup_controller_test.go | 14 +++++ internal/selfhosted/oidc.go | 2 +- internal/selfhosted/oidc/id_provider.go | 19 ++++--- internal/selfhosted/selfhosted.go | 2 +- 5 files changed, 76 insertions(+), 16 deletions(-) diff --git a/internal/client/aws.go b/internal/client/aws.go index a237c52..e376676 100644 --- a/internal/client/aws.go +++ b/internal/client/aws.go @@ -11,8 +11,10 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/iam" + iamtypes "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3/types" + "github.com/aws/aws-sdk-go-v2/service/sts" "github.com/aws/smithy-go" ) @@ -22,6 +24,11 @@ type AwsClientFactory struct { type AwsIamAPI interface { CreateOpenIDConnectProvider(ctx context.Context, params *iam.CreateOpenIDConnectProviderInput, optFns ...func(*iam.Options)) (*iam.CreateOpenIDConnectProviderOutput, error) + DeleteOpenIDConnectProvider(ctx context.Context, params *iam.DeleteOpenIDConnectProviderInput, optFns ...func(*iam.Options)) (*iam.DeleteOpenIDConnectProviderOutput, error) +} + +type AwsStsAPI interface { + GetCallerIdentity(ctx context.Context, params *sts.GetCallerIdentityInput, optFns ...func(*sts.Options)) (*sts.GetCallerIdentityOutput, error) } type AwsS3API interface { @@ -36,6 +43,7 @@ type AwsS3API interface { type AwsClient interface { IamClient() *AwsIamClient + StsClient() *AwsStsClient S3Client(region, bucketName string) *AwsS3Client } @@ -55,6 +63,12 @@ func (a *AwsClientFactory) IamClient() *AwsIamClient { } } +func (a *AwsClientFactory) StsClient() *AwsStsClient { + return &AwsStsClient{ + sts.NewFromConfig(a.config), + } +} + func (a *AwsClientFactory) S3Client(bucketName, region string) *AwsS3Client { return &AwsS3Client{ s3.NewFromConfig(a.config), @@ -63,6 +77,12 @@ func (a *AwsClientFactory) S3Client(bucketName, region string) *AwsS3Client { } } +type AwsIamClient struct { + Client AwsIamAPI +} +type AwsStsClient struct { + Client AwsStsAPI +} type AwsS3Client struct { Client AwsS3API region string @@ -218,21 +238,42 @@ func (a *AwsS3Client) Region() string { return a.region } -type AwsIamClient struct { - Client AwsIamAPI -} - // CreateOIDCProvider creates an OpenID Connect (OIDC) provider in AWS IAM. -func (a *AwsIamClient) CreateOIDCProvider(ctx context.Context, providerUrl string) (string, error) { - result, err := a.Client.CreateOpenIDConnectProvider(ctx, &iam.CreateOpenIDConnectProviderInput{ +func (a *AwsIamClient) CreateOIDCProvider(ctx context.Context, providerUrl string) error { + _, err := a.Client.CreateOpenIDConnectProvider(ctx, &iam.CreateOpenIDConnectProviderInput{ Url: &providerUrl, ClientIDList: []string{"sts.amazonaws.com"}, ThumbprintList: []string{ strings.Repeat("x", 40), // Thumbprint is required, but IAM will retrieve and use the top intermediate CA thumbprint of the OpenID Connect identity provider server certificate. }, }) + if err != nil { + var entityAlreadyExists *iamtypes.EntityAlreadyExistsException + if errors.As(err, &entityAlreadyExists) { + log.Println("skipped error", err) + } else { + return err + } + } + return nil +} + +// DeleteOIDCProvider deletes an OpenID Connect (OIDC) provider in AWS IAM. +func (a *AwsIamClient) DeleteOIDCProvider(ctx context.Context, accountId, issuerHostPath string) error { + _, err := a.Client.DeleteOpenIDConnectProvider(ctx, &iam.DeleteOpenIDConnectProviderInput{ + OpenIDConnectProviderArn: aws.String(fmt.Sprintf("arn:aws:iam::%s:oidc-provider/%s", accountId, issuerHostPath)), + }) + if err != nil { + return err + } + return nil +} + +func (a *AwsStsClient) GetAccountId() (string, error) { + req, err := a.Client.GetCallerIdentity(context.TODO(), &sts.GetCallerIdentityInput{}) if err != nil { return "", err } - return *result.OpenIDConnectProviderArn, nil + + return *req.Account, nil } diff --git a/internal/controller/irsasetup_controller_test.go b/internal/controller/irsasetup_controller_test.go index 9be8a26..924d6cc 100644 --- a/internal/controller/irsasetup_controller_test.go +++ b/internal/controller/irsasetup_controller_test.go @@ -22,6 +22,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/aws/aws-sdk-go-v2/service/sts" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "k8s.io/apimachinery/pkg/api/errors" @@ -126,15 +127,28 @@ func (m *mockAwsClient) S3Client(region, bucketName string) *awsclient.AwsS3Clie return &awsclient.AwsS3Client{Client: &mockAwsS3API{}} } +func (m *mockAwsClient) StsClient() *awsclient.AwsStsClient { + return &awsclient.AwsStsClient{Client: &mockAwsStsAPI{}} +} + type ( mockAwsIamAPI struct{} mockAwsS3API struct{} + mockAwsStsAPI struct{} ) func (m *mockAwsIamAPI) CreateOpenIDConnectProvider(ctx context.Context, params *iam.CreateOpenIDConnectProviderInput, optFns ...func(*iam.Options)) (*iam.CreateOpenIDConnectProviderOutput, error) { return &iam.CreateOpenIDConnectProviderOutput{OpenIDConnectProviderArn: aws.String("arn::mock")}, nil } +func (m *mockAwsIamAPI) DeleteOpenIDConnectProvider(ctx context.Context, params *iam.DeleteOpenIDConnectProviderInput, optFns ...func(*iam.Options)) (*iam.DeleteOpenIDConnectProviderOutput, error) { + return &iam.DeleteOpenIDConnectProviderOutput{}, nil +} + +func (m *mockAwsStsAPI) GetCallerIdentity(ctx context.Context, params *sts.GetCallerIdentityInput, optFns ...func(*sts.Options)) (*sts.GetCallerIdentityOutput, error) { + return &sts.GetCallerIdentityOutput{Account: aws.String("123456789012")}, nil +} + func (m *mockAwsS3API) CreateBucket(ctx context.Context, params *s3.CreateBucketInput, optFns ...func(*s3.Options)) (*s3.CreateBucketOutput, error) { return nil, nil } diff --git a/internal/selfhosted/oidc.go b/internal/selfhosted/oidc.go index a9fcb8d..2bfcdda 100644 --- a/internal/selfhosted/oidc.go +++ b/internal/selfhosted/oidc.go @@ -8,7 +8,7 @@ type OIDCIssuerMeta interface { } type OIDCIdP interface { - Create(ctx context.Context) (string, error) + Create(ctx context.Context) error IsUpdate() (bool, error) Update(ctx context.Context) error Delete(ctx context.Context) error diff --git a/internal/selfhosted/oidc/id_provider.go b/internal/selfhosted/oidc/id_provider.go index 1ed3b0b..1e321ff 100644 --- a/internal/selfhosted/oidc/id_provider.go +++ b/internal/selfhosted/oidc/id_provider.go @@ -9,20 +9,22 @@ import ( type AwsIdP struct { iamClient *client.AwsIamClient + stsClient *client.AwsStsClient issuerMeta selfhosted.OIDCIssuerMeta } func NewAwsIdP(awsConfig client.AwsClient, issuerMeta selfhosted.OIDCIssuerMeta) (*AwsIdP, error) { iamClient := awsConfig.IamClient() - return &AwsIdP{iamClient, issuerMeta}, nil + stsClient := awsConfig.StsClient() + return &AwsIdP{iamClient, stsClient, issuerMeta}, nil } -func (a *AwsIdP) Create(ctx context.Context) (string, error) { - arn, err := a.iamClient.CreateOIDCProvider(ctx, a.issuerMeta.IssuerUrl()) +func (a *AwsIdP) Create(ctx context.Context) error { + err := a.iamClient.CreateOIDCProvider(ctx, a.issuerMeta.IssuerUrl()) if err != nil { - return "", err + return err } - return arn, nil + return nil } func (a *AwsIdP) Update(ctx context.Context) error { @@ -34,6 +36,9 @@ func (a *AwsIdP) IsUpdate() (bool, error) { } func (a *AwsIdP) Delete(ctx context.Context) error { - // TODO: - return nil + accountId, err := a.stsClient.GetAccountId() + if err != nil { + return err + } + return a.iamClient.DeleteOIDCProvider(ctx, accountId, a.issuerMeta.IssuerHostPath()) } diff --git a/internal/selfhosted/selfhosted.go b/internal/selfhosted/selfhosted.go index 92ef63d..2c4ea7f 100644 --- a/internal/selfhosted/selfhosted.go +++ b/internal/selfhosted/selfhosted.go @@ -18,7 +18,7 @@ func Execute(ctx context.Context, factory OIDCIdPFactory, forceUpdate bool) erro if err != nil { return err } - _, err = idp.Create(ctx) + err = idp.Create(ctx) if err != nil { return err }