11package account
22
33import (
4- "context"
54 "fmt"
6- "strings"
75
86 "github.com/aws/aws-sdk-go/aws"
9- "github.com/aws/aws-sdk-go/service/sts"
10- awsv1alpha1 "github.com/openshift/aws-account-operator/pkg/apis/aws/v1alpha1"
117 "github.com/spf13/cobra"
12- corev1 "k8s.io/api/core/v1"
13- "k8s.io/apimachinery/pkg/types"
148
159 "k8s.io/cli-runtime/pkg/genericclioptions"
16- "k8s.io/klog"
1710 cmdutil "k8s.io/kubectl/pkg/cmd/util"
18- "sigs.k8s.io/controller-runtime/pkg/client"
1911
20- "github.com/openshift/osd-utils-cli/cmd/common"
21- "github.com/openshift/osd-utils-cli/pkg/k8s"
12+ k8spkg "github.com/openshift/osd-utils-cli/pkg/k8s"
2213 awsprovider "github.com/openshift/osd-utils-cli/pkg/provider/aws"
2314)
2415
@@ -36,62 +27,41 @@ func newCmdCli(streams genericclioptions.IOStreams, flags *genericclioptions.Con
3627 },
3728 }
3829
39- cliCmd .Flags ().StringVar (& ops .accountNamespace , "account-namespace" , common .AWSAccountNamespace ,
40- "The namespace to keep AWS accounts. The default value is aws-account-operator." )
41- cliCmd .Flags ().StringVarP (& ops .accountName , "account-name" , "a" , "" , "The AWS Account CR name to generate the credentials for" )
42- cliCmd .Flags ().StringVarP (& ops .accountID , "account-id" , "i" , "" , "The AWS Account ID we need to create temporary AWS credentials for -- This argument will not work for CCS accounts" )
43- cliCmd .Flags ().StringVarP (& ops .clusterID , "cluster-id" , "C" , "" , "The Internal Cluster ID from Hive to create AWS console URL for" )
44- cliCmd .Flags ().StringVarP (& ops .profile , "aws-profile" , "p" , "" , "specify AWS profile" )
45- cliCmd .Flags ().StringVarP (& ops .cfgFile , "aws-config" , "c" , "" , "specify AWS config file path" )
46- cliCmd .Flags ().StringVarP (& ops .region , "aws-region" , "r" , common .DefaultRegion , "specify AWS region" )
47- cliCmd .Flags ().Int64VarP (& ops .cliDuration , "duration" , "d" , 3600 , "The duration of the cli token. " +
48- "Default value is 3600 seconds(1 hour)" )
30+ ops .k8sclusterresourcefactory .AttachCobraCliFlags (cliCmd )
31+
4932 cliCmd .Flags ().BoolVarP (& ops .verbose , "verbose" , "v" , false , "Verbose output" )
5033
5134 return cliCmd
5235}
5336
5437// cliOptions defines the struct for running the cli command
5538type cliOptions struct {
56- accountName string
57- accountID string
58- accountNamespace string
59- clusterID string
60- cliDuration int64
61-
62- // AWS config
63- region string
64- profile string
65- cfgFile string
39+ k8sclusterresourcefactory k8spkg.ClusterResourceFactoryOptions
6640
6741 verbose bool
6842
69- flags * genericclioptions.ConfigFlags
7043 genericclioptions.IOStreams
71- kubeCli client.Client
7244}
7345
7446func newCliOptions (streams genericclioptions.IOStreams , flags * genericclioptions.ConfigFlags ) * cliOptions {
7547 return & cliOptions {
76- flags : flags ,
48+ k8sclusterresourcefactory : k8spkg.ClusterResourceFactoryOptions {
49+ Flags : flags ,
50+ },
7751 IOStreams : streams ,
7852 }
7953}
8054
8155func (o * cliOptions ) complete (cmd * cobra.Command ) error {
82- // account CR name and account ID cannot be empty at the same time
83- if o .accountName == "" && o .accountID == "" && o .clusterID == "" {
84- return cmdutil .UsageErrorf (cmd , "AWS account CR name, AWS account ID and Cluster ID cannot be empty at the same time" )
85- }
86-
87- if ! o .hasOnlyOneTarget () {
88- return cmdutil .UsageErrorf (cmd , "AWS account CR name, AWS account ID, or Cluster ID cannot be set at the same time" )
56+ k8svalid , err := o .k8sclusterresourcefactory .ValidateIdentifiers ()
57+ if ! k8svalid {
58+ if err != nil {
59+ return err
60+ }
8961 }
9062
91- // only initialize kubernetes client when account name or cluster ID is set
92- if o .accountName != "" || o .clusterID != "" {
93- var err error
94- o .kubeCli , err = k8s .NewClient (o .flags )
63+ awsvalid , err := o .k8sclusterresourcefactory .Awscloudfactory .ValidateIdentifiers ()
64+ if ! awsvalid {
9565 if err != nil {
9666 return err
9767 }
@@ -100,118 +70,17 @@ func (o *cliOptions) complete(cmd *cobra.Command) error {
10070 return nil
10171}
10272
103- func (o * cliOptions ) hasOnlyOneTarget () bool {
104- targets := []string {o .accountName , o .accountID , o .clusterID }
105- targetCount := 0
106- for _ , t := range targets {
107- if t != "" {
108- targetCount ++
109- }
110- }
111- return targetCount == 1
112- }
113-
11473func (o * cliOptions ) run () error {
115- var err error
116- awsClient , err := awsprovider .NewAwsClient (o .profile , o .region , o .cfgFile )
117- if err != nil {
118- return err
119- }
120-
121- ctx := context .TODO ()
122- var accountID string
123- if o .clusterID != "" {
124- accountClaim , err := k8s .GetAccountClaimFromClusterID (ctx , o .kubeCli , o .clusterID )
125- if err != nil {
126- return err
127- }
128- if accountClaim == nil {
129- return fmt .Errorf ("Could not find any accountClaims for cluster with ID: %s" , o .clusterID )
130- }
131- if accountClaim .Spec .AccountLink == "" {
132- return fmt .Errorf ("An unexpected error occured: the AccountClaim has no Account" )
133- }
134- o .accountName = accountClaim .Spec .AccountLink
135- }
136- var isBYOC bool
137- var acctSuffix string
138- if o .accountName != "" {
139- account , err := k8s .GetAWSAccount (ctx , o .kubeCli , o .accountNamespace , o .accountName )
140- if err != nil {
141- return err
142- }
143- accountID = account .Spec .AwsAccountID
144- isBYOC = account .Spec .BYOC
145- acctSuffix = account .Labels ["iamUserId" ]
146- } else {
147- accountID = o .accountID
148- isBYOC = false
149- }
150-
151- callerIdentityOutput , err := awsClient .GetCallerIdentity (& sts.GetCallerIdentityInput {})
74+ awsClient , err := o .k8sclusterresourcefactory .GetCloudProvider (o .verbose )
15275 if err != nil {
153- klog .Error ("Fail to get caller identity. Could you please validate the credentials?" )
15476 return err
15577 }
156- if o .verbose {
157- fmt .Fprintln (o .Out , callerIdentityOutput )
158- }
159-
160- splitArn := strings .Split (* callerIdentityOutput .Arn , "/" )
161- username := splitArn [1 ]
162- sessionName := fmt .Sprintf ("RH-SRE-%s" , username )
163-
164- // If BYOC we need to role-chain to use the right creds.
165- // Use the OrgAccess Role by default, override if BYOC
166- roleName := awsv1alpha1 .AccountOperatorIAMRole
167-
168- // TODO: Come back to this and do a lookup for the account CR if the account ID is the only one set so we can do this too.
169- if isBYOC {
170- cm := & corev1.ConfigMap {}
171- err = o .kubeCli .Get (ctx , types.NamespacedName {Namespace : awsv1alpha1 .AccountCrNamespace , Name : awsv1alpha1 .DefaultConfigMap }, cm )
172- if err != nil {
173- klog .Error ("There was an error getting the configmap." )
174- return err
175- }
176- roleArn := cm .Data ["CCS-Access-Arn" ]
177-
178- if roleArn == "" {
179- klog .Error ("Empty SRE Jump Role in ConfigMap" )
180- return fmt .Errorf ("Empty ConfigMap Value" )
181- }
18278
183- // Build the role-name for Access:
184- if acctSuffix == "" {
185- klog .Error ("Unexpected error parsing the account CR suffix" )
186- return fmt .Errorf ("Unexpected error parsing the account CR suffix." )
187- }
188- roleName = fmt .Sprintf ("BYOCAdminAccess-%s" , acctSuffix )
189-
190- // Get STS Credentials
191- if o .verbose {
192- fmt .Printf ("Elevating Access to SRE Jump Role for user %s\n " , sessionName )
193- }
194- creds , err := awsprovider .GetAssumeRoleCredentials (awsClient , & o .cliDuration , aws .String (sessionName ), aws .String (roleArn ))
195- if err != nil {
196- klog .Error ("Failed to get jump-role creds for CCS" )
197- return err
198- }
199-
200- awsClientInput := & awsprovider.AwsClientInput {
201- AccessKeyID : * creds .AccessKeyId ,
202- SecretAccessKey : * creds .SecretAccessKey ,
203- SessionToken : * creds .SessionToken ,
204- Region : "us-east-1" ,
205- }
206- // New Client with STS Credentials
207- awsClient , err = awsprovider .NewAwsClientWithInput (awsClientInput )
208- if err != nil {
209- klog .Error ("Failed to assume jump-role for CCS" )
210- return err
211- }
212- }
213- credentials , err := awsprovider .GetAssumeRoleCredentials (awsClient , & o .cliDuration ,
214- callerIdentityOutput .UserId , aws .String (fmt .Sprintf ("arn:aws:iam::%s:role/%s" , accountID , roleName )))
79+ credentials , err := awsprovider .GetAssumeRoleCredentials (awsClient , & o .k8sclusterresourcefactory .Awscloudfactory .ConsoleDuration ,
80+ o .k8sclusterresourcefactory .Awscloudfactory .CallerIdentity .UserId ,
81+ aws .String (fmt .Sprintf ("arn:aws:iam::%s:role/%s" ,
82+ o .k8sclusterresourcefactory .AccountID ,
83+ o .k8sclusterresourcefactory .Awscloudfactory .RoleName )))
21584 if err != nil {
21685 return err
21786 }
0 commit comments