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

feat(cli-plugin-contract): introduce a public contract between CLI and plugins #32111

Merged
merged 20 commits into from
Dec 27, 2024

Conversation

otaviomacedo
Copy link
Contributor

@otaviomacedo otaviomacedo commented Nov 13, 2024

The contract between the CLI and credential provider plugins is not publicly defined.

Extract the types involved in the CLI-plugin communication into a new package, @aws-cdk/cli-plugin-contract, and update all references in the CLI code.

Closes #32099, closes https://github.com/aws/aws-cdk-cli/issues/6, closes #19564

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@aws-cdk-automation aws-cdk-automation requested a review from a team November 13, 2024 14:20
@github-actions github-actions bot added effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2 labels Nov 13, 2024
@mergify mergify bot added the contribution/core This is a PR that came from AWS. label Nov 13, 2024
Copy link
Collaborator

@aws-cdk-automation aws-cdk-automation left a comment

Choose a reason for hiding this comment

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

The pull request linter has failed. See the aws-cdk-automation comment below for failure reasons. If you believe this pull request should receive an exemption, please comment and provide a justification.

A comment requesting an exemption should contain the text Exemption Request. Additionally, if clarification is needed add Clarification Request to a comment.

@aws-cdk-automation aws-cdk-automation added the pr/needs-cli-test-run This PR needs CLI tests run against it. label Nov 13, 2024
@otaviomacedo otaviomacedo added the pr-linter/exempt-integ-test The PR linter will not require integ test changes label Nov 13, 2024
Copy link

codecov bot commented Nov 13, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 80.64%. Comparing base (07e6dd3) to head (87de2e2).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #32111      +/-   ##
==========================================
- Coverage   80.64%   80.64%   -0.01%     
==========================================
  Files         107      107              
  Lines        6996     6994       -2     
  Branches     1290     1290              
==========================================
- Hits         5642     5640       -2     
  Misses       1175     1175              
  Partials      179      179              
Flag Coverage Δ
suite.unit 80.64% <100.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
packages/aws-cdk 80.64% <100.00%> (-0.01%) ⬇️

*
* Guaranteed to be called only if canProvideCredentails() returned true at some point.
*/
getProvider(accountId: string, mode: Mode): Promise<AwsCredentials>;
Copy link
Contributor

@mrgrain mrgrain Nov 13, 2024

Choose a reason for hiding this comment

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

We change this to a strongly typed string, we can make this package types only.

Suggested change
getProvider(accountId: string, mode: Mode): Promise<AwsCredentials>;
getProvider(accountId: string, mode: 'ForReading' | 'ForWriting'): Promise<AwsCredentials>;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This would be a breaking change for plugins, which are expecting a number (ForReading = 0, ForWriting = 1).

Copy link
Contributor

Choose a reason for hiding this comment

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

getProvider(accountId: string, mode: 0 | 1): Promise<AwsCredentials>;
getProviderEx(accountId: string, mode: 'ForReading' | 'ForWriting'): Promise<AwsCredentials>;

?

/**
* A list of credential provider sources
*/
export interface CredentialProviderSourceRepository {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd happily rename this interface if someone has a better suggestion.

Copy link
Contributor

Choose a reason for hiding this comment

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

PluginHost ?

It's technically also for lookup plugins, for example.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we call it PluginHost, what should we call the class that implements it in the CLI?

getPromise?: () => Promise<void>;
}

export enum Mode {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've considered making this a const enum but, given the documented pitfalls, I've decided against it. This value will probably be used only once during the execution of the plugin, which itself is part of much bigger CDK command execution. So the cost of additional indirection when accessing enum values is negligible.

Copy link
Contributor

Choose a reason for hiding this comment

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

The goal of that was more to avoid having plugins take a runtime dependency on this package. They should be able to take only a devDependency on this package.

What is the concrete pitfall you're concerned about?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All three of them. If you look at the approaches to avoid them, they boil down to "do not use this feature if an external package is going to consume this enum", which is exactly the case here.

@otaviomacedo otaviomacedo marked this pull request as ready for review November 25, 2024 11:29
@otaviomacedo otaviomacedo requested a review from a team as a code owner November 25, 2024 11:29
rix0rrr added a commit that referenced this pull request Dec 2, 2024
The CLI immediately invokes credential *providers* to produce
*credentials*, and passes the credentials around instead of the
providers. This means that if short-lived credentials expire (like
session credentials from roles), there is no way to refresh them.

CLI calls will start to fail if that happens.

To fix this, instead of resolving providers to credentials, pass
providers around instead.

Implications for auth plugins
-------------

This widens the plugin protocol: the new plugin protocol *forced* a
translation to V3 credentials, and had no way to return V3 providers.
While it is now possible to return V3 Credential Providers from the
plugin protocol, plugin writers cannot easily take advantage of that
protocol because there have been ~8 CLI releases that only support V3
credentials and will fail at runtime of V3 providers are returned.

To support this, pass a new options argument into `getProvider()`:
this will indicate whether V3 Providers are supported or not. Plugins
can return a provider if the CLI indicates that it supports V3
providers, and avoid doing that if the CLI indicates it won't. That way,
plugins can be rewritten to take advantage of returning V3 providers
without crashing on CLI versions `2.167.0..(this releases)`.

This also affects #32111 in which the plugin contract is being moved.
rix0rrr added a commit that referenced this pull request Dec 4, 2024
The CLI immediately invokes credential *providers* to produce
*credentials*, and passes the credentials around instead of the
providers. This means that if short-lived credentials expire (like
session credentials from roles), there is no way to refresh them.

CLI calls will start to fail if that happens.

To fix this, instead of resolving providers to credentials, pass
providers around instead.

Implications for auth plugins
-------------

This widens the plugin protocol: the new plugin protocol *forced* a
translation to V3 credentials, and had no way to return V3 providers.
While it is now possible to return V3 Credential Providers from the
plugin protocol, plugin writers cannot easily take advantage of that
protocol because there have been ~8 CLI releases that only support V3
credentials and will fail at runtime of V3 providers are returned.

To support this, pass a new options argument into `getProvider()`: this
will indicate whether V3 Providers are supported or not. Plugins can
return a provider if the CLI indicates that it supports V3 providers,
and avoid doing that if the CLI indicates it won't. That way, plugins
can be rewritten to take advantage of returning V3 providers without
crashing on CLI versions `2.167.0..(this releases)`.

This also affects #32111 in which the plugin contract is being moved.

Closes #32287.

----

*By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache-2.0 license*
@aws-cdk-automation
Copy link
Collaborator

➡️ PR build request submitted to test-main-pipeline ⬅️

A maintainer must now check the pipeline and add the pr-linter/cli-integ-tested label once the pipeline succeeds.

@rix0rrr rix0rrr added the pr-linter/cli-integ-tested Assert that any CLI changes have been integ tested label Dec 27, 2024
@aws-cdk-automation aws-cdk-automation dismissed their stale review December 27, 2024 09:35

✅ Updated pull request passes all PRLinter validations. Dismissing previous PRLinter review.

@aws-cdk-automation aws-cdk-automation removed the pr/needs-cli-test-run This PR needs CLI tests run against it. label Dec 27, 2024
@github-actions github-actions bot added p1 and removed p2 labels Dec 27, 2024
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildv2Project1C6BFA3F-wQm2hXv2jqQv
  • Commit ID: 87de2e2
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

Copy link
Contributor

mergify bot commented Dec 27, 2024

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@mergify mergify bot merged commit fbaab1d into main Dec 27, 2024
25 of 26 checks passed
@mergify mergify bot deleted the otaviom/cli-plugin-contract branch December 27, 2024 10:09
Copy link

Comments on closed issues and PRs are hard for our team to see.
If you need help, please open a new issue that references this one.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 27, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
contribution/core This is a PR that came from AWS. effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p1 pr-linter/cli-integ-tested Assert that any CLI changes have been integ tested pr-linter/exempt-integ-test The PR linter will not require integ test changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

(cli): Define a plugin contract (cli): publish official plugin contract
4 participants