-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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: AWS kms signer support for forc-client #6578
base: master
Are you sure you want to change the base?
Conversation
Looks like we hit a flaky test (hopefully, as it was not failing in previous commit and now it is failing): #5376 (comment) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Kaya mostly looks good. Just wondering if you can first add doc comments to all public types and functions before we merge this.
Is this entirely additive or does it include breaking behavior? |
This is entirely additive, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apart from "is is", it's good to go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK
let loader = aws_config::defaults(BehaviorVersion::latest()) | ||
.credentials_provider(DefaultCredentialsChain::builder().build().await); | ||
|
||
let loader = match std::env::var("E2E_TEST_AWS_ENDPOINT") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the right endpoint for production?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is placed here so that AwsConfig can be configured for tests in the future. It doesn't effect anything unless it is set. And by default it is not set in CI/locally. So this is here to make this thing a little bit more testable for a future PR that adds the full testing infra for aws signer.
async fn request_get_pubkey( | ||
kms: &Client, | ||
key_id: String, | ||
) -> std::result::Result<GetPublicKeyOutput, anyhow::Error> { | ||
kms.get_public_key() | ||
.key_id(key_id) | ||
.send() | ||
.await | ||
.map_err(Into::into) | ||
} | ||
|
||
/// Decode an AWS KMS Pubkey response. | ||
fn decode_pubkey(resp: &GetPublicKeyOutput) -> std::result::Result<Vec<u8>, anyhow::Error> { | ||
let raw = resp | ||
.public_key | ||
.as_ref() | ||
.ok_or(anyhow::anyhow!("public key not found"))?; | ||
Ok(raw.clone().into_inner()) | ||
} | ||
|
||
async fn sign_with_kms( | ||
client: &aws_sdk_kms::Client, | ||
key_id: &str, | ||
public_key_bytes: &[u8], | ||
message: Message, | ||
) -> anyhow::Result<fuel_crypto::Signature> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I think it'd be cleaner to make these part of the AwsSigner impl
script_gas_limit | ||
// Dry run tx and get `gas_used` | ||
} else { | ||
get_script_gas_used(tb.clone().finalize_without_signature_inner(), &provider).await? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this no longer needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we no longer need to maintain our own signing logic for WalletUnlocked
as the signer is abstracted as ForcClientAccount
which implements a Signer
and Account
from SDK. The refactor that moves the Wallet into ForcClientAccount
makes the custom signing logic obsolete. As a byproduct of that, we no longer need to maintain this custom signing logic for scripts. We can simply use SDK to do the signing as ForcClientAccount
is a valid signer/account from the perspective of the SDK.
We were already doing this for forc-deploy and simply creating the deployment transaction using SDK. Now the same de-duplication is done to the forc-run as well.
Summary is that the refactor we did makes it possible to remove all custom signing logic we have, by moving to use SDK for signatures completely.
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use std::collections::BTreeMap; | ||
use std::collections::HashMap; | ||
use fuels::types::bech32::Bech32Address; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we update the tests to remove Bech32 usage?
); | ||
let v = recovery_id.is_y_odd() as u8; | ||
let mut signature = <[u8; 64]>::from(sig.to_bytes()); | ||
signature[32] = (v << 7) | (signature[32] & 0x7f); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this doing? It would be great to have more detailed comments here.
Description
closes #6560.
closes #6559.
This PR adds AWS kms signer support. Which is enabled if
--aws-kms-signer <ARN>
is present. If that is the case, an aws client is created which is used to create a AwsSigner.With this PR, we are able to supply a signing arn and with that we can sign a transaction. This enables being able to revoke signing authority for aws kms managed keys. So we can control deployments and owner/target changes for a proxy contract. Effectively enabling multi-sig like proxy contracts via aws kms.