Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HOSTEDCP-1561: Move HCP Product CLI to STS #4027

Merged
merged 7 commits into from
May 22, 2024

Conversation

Patryk-Stefanski
Copy link
Contributor

What this PR does / why we need it:

Which issue(s) this PR fixes (optional, use fixes #<issue_number>(, fixes #<issue_number>, ...) format, where issue_number might be a GitHub issue, or a Jira story:
Fixes #

Checklist

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 13, 2024
Copy link
Contributor

openshift-ci bot commented May 13, 2024

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@Patryk-Stefanski Patryk-Stefanski changed the title Hostedcp 1561 HOSTEDCP-1561: Move HCP Product CLI to STS May 13, 2024
@openshift-ci-robot
Copy link

openshift-ci-robot commented May 13, 2024

@Patryk-Stefanski: This pull request references HOSTEDCP-1561 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "4.16.0" version, but no target version was set.

In response to this:

What this PR does / why we need it:

Which issue(s) this PR fixes (optional, use fixes #<issue_number>(, fixes #<issue_number>, ...) format, where issue_number might be a GitHub issue, or a Jira story:
Fixes #

Checklist

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label May 13, 2024
Copy link

netlify bot commented May 13, 2024

Deploy Preview for hypershift-docs ready!

Name Link
🔨 Latest commit 01d10a4
🔍 Latest deploy log https://app.netlify.com/sites/hypershift-docs/deploys/664486bb36a72b00087493cf
😎 Deploy Preview https://deploy-preview-4027--hypershift-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@openshift-ci openshift-ci bot added area/cli Indicates the PR includes changes for CLI and removed do-not-merge/needs-area labels May 13, 2024
cmd/cluster/aws/create.go Outdated Show resolved Hide resolved
cmd/cluster/aws/destroy.go Outdated Show resolved Hide resolved
cmd/consolelogs/aws/getlogs.go Outdated Show resolved Hide resolved
cmd/consolelogs/aws/getlogs.go Outdated Show resolved Hide resolved
)

const (
cliRolePolicy = `{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't @muraee just add this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes he did, This PR wasn't meant to be reviewed yet (but I always welcome an early review :) ) and I was using his work for testing. So this comment and the following comments should have been left on his pr. In this case Im more than happy to make any changes that @muraee approves.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. His PR already went in, let's get these following comments addressed in this PR then.

return nil
}

func assumeRoleTrustPolicy(ctx context.Context, client *sts.STS) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it has a lot in common with iam.go - let's refactor to share where we can, please.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as #4027 (comment)

return assumeRolePolicy, nil
}

func (o *CreateCLIRoleOptions) ParseAdditionalTags() ([]*iam.Tag, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a copy-pasta from iam.go - please DRY it out

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as #4027 (comment)

@@ -155,7 +169,17 @@ func (o *CreateIAMOptions) CreateIAM(ctx context.Context, client crclient.Client
return nil, err
}

awsSession := awsutil.NewSession("cli-create-iam", o.AWSCredentialsFile, o.AWSKey, o.AWSSecretKey, o.Region)
var awsSession *session.Session
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sheer number of places where you need to add these new flags and validation is too high to be tenable. Let's break out some

type AWSCredentialOptions struct {
    RoleARN string
    STSCreds string
    // whatever else
}

func DefaultOptions() *AWSCredentialOptions {
    return &AWSCredentialOptions{/* place any meaningful defaults here */}
}

func BindOptions(opts *AWSCredentialOptions, flags *pflag.FlagSet) {
    flags.StringVar(&opts.RoleArn, "role-arn", opts.RoleArn, "The ARN of the role to assume when creating the iam.")
    flags.StringVar(&opts.StsCredentialsFile, "sts-creds", opts.StsCredentialsFile, "Path to STS credentials file to use when assuming the role.")
}

func (opts *AWSCredentialOptions) Validate() error {
    /* add validation here */
}

Then, embed this struct into the others where needed and call BindOptions() on it where flags are being added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as #4027 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevekuznetsov because of the --secret-creds flag we sometimes need the roleArn without the need of stsCreds. I have created a new util validation function for validating the required flags here cmd/util/credentials_validation.go

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's find a factoring where we bind the flags once in the repo and validate them in one flow. If that means that the options need parameters on creation and/or validation, so be it. For all commands that want to authenticate to AWS, let's provide a package that lets them bind the flags they need and get an AWS session out the other end. A good litmus test IMHO will be that this PR adds only one line that binds sts-creds as a flag to a struct member.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevekuznetsov Just reading over the PR and I agree with you but since I'm leaving for PTO today and this feature is time sensitive I think this would be more of nice to have in this scenario. @muraee I don't know if you have the time to look into this approach or maybe this can be a separate Jira in our backlog?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't speak to timelines but I think trending in the direction I outline here will help us immensely with maintenance of the codebase.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Patryk-Stefanski given that you'll be out, is it ok if we get someone else to take over the PR after today? I don't think @stevekuznetsov's are that big, but agree they would help with the maintenance of the code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@csrwng I have added @muraee as contributor and I can add anyone else aswell just let me know.

TrustPolicy string
PermissionsPolicy string

additionalIAMTags []*iam.Tag
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this not exported?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as #4027 (comment)

cmd/infra/aws/util/util.go Outdated Show resolved Hide resolved
@Patryk-Stefanski Patryk-Stefanski marked this pull request as ready for review May 15, 2024 14:30
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 15, 2024
@openshift-ci openshift-ci bot requested review from csrwng and hasueki May 15, 2024 14:32
}

if credentialsFile != "" {
stsSessionOpts.SharedConfigFiles = append(stsSessionOpts.SharedConfigFiles, credentialsFile)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is expecting an aws credentials file, I think it should expect the output of aws sts get-session-token --output json instead and then parse it and extract necessary fields.
Otherwise, the use will have to do 1 extra step to format the sts-creds file before passing it to the cli. If we do this, we can validate that the session_token exist and throw an error/warning that the user is not using temporary credentials.

@openshift-ci openshift-ci bot added the area/testing Indicates the PR includes changes for e2e testing label May 17, 2024
Copy link
Contributor

@csrwng csrwng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some naming nits, otherwise lgtm

supportawsutil "github.com/openshift/hypershift/support/awsutil"
)

func NewStsSession(agent, rolenArn, region string, assumeRoleCreds *credentials.Credentials) (*session.Session, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: s/Sts/STS/

Credentials Credentials `json:"Credentials"`
}

rawStsCreds, err := os.ReadFile(credentialsFile)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: s/Sts/STS/

AWSCredentialsFile string

RoleArn string
StsCredentialsFile string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: s/Sts/STS/

@muraee
Copy link
Contributor

muraee commented May 17, 2024

/label tide/merge-method-squash

@openshift-ci openshift-ci bot added the tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges. label May 17, 2024
return nil
}

if opts.AWSPlatform.AWSCredentialsOpts.AWSCredentialsFile == "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we're doing this check again? Wouldn't Validate above catch it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validate above is executed when the CredentialsSecret is not set.

If CredentialsSecret is set we want to only check that role-arn is required, but only if AWSCredentialsFile is not set. i.e. AWSCredentialsFile has priority over credentialSecret (this is the current behavior, I can change it if it doesn't make sense)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In some follow-up, might be good to check with whoever is using this secret flag thing and see if they can stop, it's a huge hassle to support it and asking folks to pass in the options they need verbatim would be a lot easier to reason about.

@csrwng
Copy link
Contributor

csrwng commented May 17, 2024

/approve

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 17, 2024
@@ -167,7 +168,7 @@ type KubevirtPlatformCreateOptions struct {
}

type AWSPlatformOptions struct {
AWSCredentialsFile string
AWSCredentialsOpts awsutil.AWSCredentialsOptions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You do not need to change this now, but FWIW if you had embedded the awsutil.AWSCredentialsOptions it would have required a much smaller diff (and a lot less typing!)

Copy link
Contributor

@stevekuznetsov stevekuznetsov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Couple small comments

@@ -48,11 +46,13 @@ func NewCreateCommand(opts *core.CreateOptions) *cobra.Command {
cmd.Flags().StringVar(&opts.AWSPlatform.EndpointAccess, "endpoint-access", opts.AWSPlatform.EndpointAccess, "Access for control plane endpoints (Public, PublicAndPrivate, Private)")
cmd.Flags().StringVar(&opts.AWSPlatform.EtcdKMSKeyARN, "kms-key-arn", opts.AWSPlatform.EtcdKMSKeyARN, "The ARN of the KMS key to use for Etcd encryption. If not supplied, etcd encryption will default to using a generated AESCBC key.")
cmd.Flags().BoolVar(&opts.AWSPlatform.EnableProxy, "enable-proxy", opts.AWSPlatform.EnableProxy, "If a proxy should be set up, rather than allowing direct internet access from the nodes")
cmd.Flags().StringVar(&opts.CredentialSecretName, "secret-creds", opts.CredentialSecretName, "A Kubernetes secret with needed AWS platform credentials: aws-creds, pull-secret, and a base-domain value. The secret must exist in the supplied \"--namespace\". If a value is provided through the flag '--pull-secret', that value will override the pull-secret value in 'secret-creds'.")
cmd.Flags().StringVar(&opts.CredentialSecretName, "secret-creds", opts.CredentialSecretName, "A Kubernetes secret with needed AWS platform credentials: sts-creds, pull-secret, and a base-domain value. The secret must exist in the supplied \"--namespace\". If a value is provided through the flag '--pull-secret', that value will override the pull-secret value in 'secret-creds'.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing what we expect in this secret is breaking for any existing users of the CLI that are using the flag and secret today - if we have such users, this is not safe to do.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is used by ACM, we already communicated the new changes with them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the path for this not to be breaking, then? They will have to update the secret to contain both values before this merges and is rolled out?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need this to merge today on our side. I don't how/when they roll out new versions.

return nil
}

if opts.AWSPlatform.AWSCredentialsOpts.AWSCredentialsFile == "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In some follow-up, might be good to check with whoever is using this secret flag thing and see if they can stop, it's a huge hassle to support it and asking folks to pass in the options they need verbatim would be a lot easier to reason about.

@@ -138,20 +138,26 @@ func DestroyCluster(ctx context.Context, o *core.DestroyOptions) error {
return core.DestroyCluster(ctx, hostedCluster, o, destroyPlatformSpecifics)
}

// ValidateCredentialInfo validates if the credentials secret name is empty, the aws-creds is not empty; validates if
// ValidateCredentialInfo validates if the credentials secret name is empty, the aws-creds or sts-creds mutually exclusive and are not empty; validates if
// the credentials secret is not empty, that it can be retrieved.
func ValidateCredentialInfo(opts *core.DestroyOptions) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this any different from the ValidateCreateCredentialInfo(opts *core.CreateOptions) error? If not, can it be written as ValidateAWSCredentialInfo(opts *core.AWSCredentialsOpts, secret string) error and shared?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or, share using a larger struct that has one more field for the secret and closes over binding the flag, validating, etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ValidateCreateCredentialInfo also validates the pull-secret while this one doesn't, so I don't see how we can share the func easily.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about

func ValidateCreateCredentialInfo(opts *core.CreateOptions) error {
    if err := ValidateAWSCredentialInfo(opts.AWSPlatform.AWSCredentialsOpts, opts.CredentialSecretName); err != nil {
        return err
    } 
    
    if len(opts.CredentialSecretName) == 0 {
        if err := util.ValidateRequiredOption("pull-secret", opts.PullSecretFile); err != nil {
            return err
        }
    }
    return nil
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed


func (opts *AWSCredentialsOptions) BindFlags(flags *pflag.FlagSet) {
flags.StringVar(&opts.AWSCredentialsFile, "aws-creds", opts.AWSCredentialsFile, "Path to an AWS credentials file")
flags.StringVar(&opts.RoleArn, "role-arn", opts.RoleArn, "The ARN of the role to assume.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you factor one of Bind* to call the other? We do not want the flag names etc to be different.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how would you do that? one marks the flags as required, the other one doesn't

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would personally not bother with the cobra.MarkFlagRequired business - you need to have the correct logic in Validate() anyway and with the programmatic re-use of the Options struct in e2e, so it's not really buying us anything.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cobra.MarkFlagRequired also helps prioritize those fields with auto completion. But not very important.
Addressed.

return NewSTSSession(agent, opts.RoleArn, region, creds)
}

return nil, fmt.Errorf("either --aws-creds or --sts-creds or --secret-creds flag must be set")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: keep the flag-related comments in the Validate(). This kind of function (GetSession(), etc) is most useful when being re-used in code, for instance how we have the e2e today creating Options structs and using them as-is. In that kind of context, there are no flags and error messages about --aws-creds from the internals of the e2e framework (or whatever other programmatic consumer there is for this) are harder to follow. This error might read something like

return nil, errors.New("could not create AWS session, no credentials were given")

Copy link
Contributor

@stevekuznetsov stevekuznetsov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label May 20, 2024
Copy link
Contributor

openshift-ci bot commented May 20, 2024

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: csrwng, Patryk-Stefanski, stevekuznetsov

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci-robot
Copy link

/retest-required

Remaining retests: 0 against base HEAD c698d1d and 2 for PR HEAD d8dd04e in total

@openshift-ci-robot
Copy link

/retest-required

Remaining retests: 0 against base HEAD c5401ca and 1 for PR HEAD d8dd04e in total

@openshift-ci-robot
Copy link

/retest-required

Remaining retests: 0 against base HEAD f91af53 and 0 for PR HEAD d8dd04e in total

@openshift-ci-robot
Copy link

/hold

Revision d8dd04e was retested 3 times: holding

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label May 21, 2024
@muraee
Copy link
Contributor

muraee commented May 21, 2024

/unhold

@openshift-ci openshift-ci bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label May 21, 2024
@muraee
Copy link
Contributor

muraee commented May 21, 2024

/override ci/prow/e2e-kubevirt-aws-ovn

Copy link
Contributor

openshift-ci bot commented May 21, 2024

@muraee: Overrode contexts on behalf of muraee: ci/prow/e2e-kubevirt-aws-ovn

In response to this:

/override ci/prow/e2e-kubevirt-aws-ovn

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Copy link
Contributor

openshift-ci bot commented May 21, 2024

@Patryk-Stefanski: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-azure d8dd04e link false /test e2e-azure

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@openshift-ci-robot
Copy link

/retest-required

Remaining retests: 0 against base HEAD 5934604 and 2 for PR HEAD d8dd04e in total

@openshift-ci-robot
Copy link

/retest-required

Remaining retests: 0 against base HEAD f20ba0d and 1 for PR HEAD d8dd04e in total

@openshift-merge-bot openshift-merge-bot bot merged commit 936f82b into openshift:main May 22, 2024
12 of 13 checks passed
@celebdor
Copy link
Contributor

/cherry-pick release-4.16

@openshift-cherrypick-robot

@celebdor: new pull request created: #4078

In response to this:

/cherry-pick release-4.16

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Tal-or pushed a commit to Tal-or/hypershift that referenced this pull request May 29, 2024
* HOSTEDCP-1561: Move HCP CLI to STS mode

* HOSTEDCP-1561: Addressing comments

* HOSTEDCP-1561: enable --secret-creds flag with sts

* HOSTEDCP-1561 extract sts cred specifics from sts-creds file

* refactor

* addressed review comments

* more refactor

---------

Co-authored-by: Mulham Raee <mraee@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/cli Indicates the PR includes changes for CLI area/testing Indicates the PR includes changes for e2e testing jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants