IMPORTANT NOTES:
- The AWS Nitro API Co-Signer is a feature recommended for customers who prefer using AWS. It is currently in early availability. Contact your Customer Success Manager for more information and to request access to this feature.
- This article will be deprecated by February 28th, 2025. For all API Co-signer documentation, visit this overview article, which also links to updated Co-signer content in the Developer Portal.
About AWS Nitro Enclaves
The AWS Nitro System is the underlying platform for Amazon's EC2 instances, providing enhanced security. AWS Nitro Enclaves enable the creation of isolated compute environments to protect and securely process data. Nitro Enclaves integrates with the AWS Key Management Service (KMS) and includes cryptographic attestation so that only authorized code can run.
Learn more about AWS Nitro Enclaves.
About the AWS Nitro API Co-Signer
The AWS Nitro API Co-Signer allows you to run a Fireblocks API Co-Signer inside an AWS Nitro Enclave. This provides the highest level of confidential security for organizations that want to run Fireblocks' API Co-Signer on AWS. The Fireblocks AWS Nitro API Co-Signer automates transaction signing, wallet approvals, and workspace update approvals.
AWS Nitro systems are the recommended AWS service for deploying Fireblocks API Co-signers.
The AWS Nitro Co-Signer uses the Customer Managed Key (CMK) within the AWS KMS service to encrypt the secrets.key file. The secrets.key file is used to encrypt the Co-Signer’s secrets database which stores the following data:
- The set of keys required for approving transactions according to Transaction Authorization Policy (TAP) rules, and workspace changes.
- Your MPC key share used to sign transactions.
Each API Co-Signer can be optionally configured to work with a unique API Co-Signer Callback Handler, an HTTPS server that can approve or reject transaction signing and configuration change requests based on custom logic implemented by the customer.
API Co-Signer transaction flow
The process for generating and signing a Fireblocks transaction using the Fireblocks REST API service and the Fireblocks API Co-Signer is as follows:
- An API transaction request is made to the Fireblocks REST API service. A new transaction is submitted via this API endpoint and generated on the Fireblocks backend.
- The transaction passes through your Transaction Authorization Policy. If approved, the transaction is sent to all Co-Signers for signing.
- The API Co-Signer receives a request to sign the transaction.
- If you don't have a Callback Handler set up, the transaction assumes approval and continues.
- If you have a Callback Handler set up, the API Co-Signer sends a secure approval request to it. The Callback Handler either approves or rejects the transaction based on its logic.
- Upon approval, the API Co-Signer engages with the Co-Signers on Fireblocks to start a mutual signing process for the transaction.
Installing the API Co-signer
To set up the API Co-Signer, follow these instructions to create a dedicated API user with signing permissions and retrieve its API key. During the API user creation process, make sure you select Proprietary AWS Nitro Enclave. At this point you need to refer to the installation guide in order to create and configure the necessary AWS resources and install the Co-signer. Once the Co-signer is installed, you will see it in the Co-signer management tab.
Important
You must complete the first five API Co-Signer installation steps within an hour of receiving an API Key to pair the API user.
API Co-Signer requirements
To set up the API Co-Signer, you must first hold an API key with signing permissions. Follow these instructions to set up your API key.
The API Co-Signer can be provisioned together with the Callback Handler. The Callback Handler processes POST requests and responds with an approval or rejection response. You can learn more about how to handle the response request and structure.
Step 1: Create an IAM role
IAM roles are used to delegate access to your AWS resources. With IAM roles, you can establish trust relationships between your trusting account and other AWS trusted accounts. The trusting account owns the resource that requires access. The trusted account contains the users who need access to the resource.
- Open the Identity and Access Management (IAM) console and go to Access Management > Roles, then select Create Role.
- On the Create role page, select the following:
- Select Next: Permissions. Click Next without making any selections.
- Select Next: Tags. This page is optional, so leave it blank unless necessary and select Next: Review.
- On the Review page, enter a name and select Create Role.
- Click on the newly created role and copy the ARN for the next step.
Step 2: Create CMK using AWS Key Management Service (KMS)
AWS KMS helps you centrally manage and securely store your keys. Follow the steps below to configure your AWS Key and set up your API Co-Signer software.
- Open the KMS console and select Create a key.
- On the Configure key page, select the following:
- Select Next. On the Add labels page, set a display name for the key in the Alias field. The Description and Tags fields are optional.
- Select Next. On the Define key administrative permissions page, choose the role that you want or leave this section blank.
- Select Next. Leave the Define key usage permissions page blank and select Next.
- Select Review and scroll down to Key policy.
Update the default policy to include statements that ensure that only the enclave you generate can access the KMS for encryption and decryption.
Your updated policy should look like this:
{
"Version": "2012-10-17",
"Id": "key-consolepolicy-3",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::945849002297:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow the Cosigner to encrypt",
"Effect": "Allow",
"Principal": {
"AWS": "<COSIGNER_IAM_ROLE_ARN>"
},
"Action": [
"kms:Encrypt",
"kms:GenerateDataKey"
],
"Resource": "*"
},
{
"Sid": "Allow the Cosigner enclave to decrypt",
"Effect": "Allow",
"Principal": {
"AWS": "<COSIGNER_IAM_ROLE_ARN>"
},
"Action": "kms:Decrypt",
"Resource": "*",
"Condition": {
"StringEqualsIgnoreCase": {
"kms:RecipientAttestation:PCR8": "<PCR8_VALUE>",
"kms:RecipientAttestation:PCR4": [
"<PCR4_VALUE_HOST_1>",
"<PCR4_VALUE_HOST_2_IF_EXISTS>"
]
}
}
}
]
}Once applied, select Confirm.
Note
PCR4 and PCR8 values are fetched during installation. PCR4 is a unique identifier of the enclave, and PCR8 is a unique identifier of the signed enclave image file generated by Fireblocks. These values do not need to be modified.
- Select the Key ID, then copy the Key ARN for later usage.
Step 3: Create an EC2 instance
Important
For the Instance Metadata Version, use V1 and V2.
- Open the EC2 Dashboard and select Launch Instance.
-
Choose an Amazon Machine Image (AMI): Search for Amazon Linux AMI (HVM) - 2 Kernel 5.10, then select Select.
-
Choose an Instance Type: Select c5a.xlarge (4 vCPUs & 8GB RAM) or m5.xlarge (4vCPU & 16GB RAM).
- Select Next: Configure Instance Details.
-
Advanced Details:
- IAM instance profile: Select the IAM Role that you created in step 3.
- Nitro Enclave: Select Enable. Note that if you selected an instance type that isn't compatible with Nitro, this field will appear grayed out.
- Select Review and Launch.
- Review Instance Launch: Review and select Launch.
- Make sure the machine meets the following networking requirements:
- No inbound connections
- When the API Co-Signer is active:
- Outbound: port 443 to https://fb-certs.s3.amazonaws.com
- Outbound: port 443 to https://registry.gitlab.com/Client-cosigner/
- Outbound: port 443 to https://mobile-api.fireblocks.io/
- Outbound: port 443 to https://fb-Clients.s3.amazonaws.com/uploads/
- During setup time and after stopping and starting the machine:
- Outbound: port 5000 to https://registry.gitlab.com/Client-cosigner/
- Outbound: port 443 to https://bootstrap.pypa.io/get-pip.py
Additionally, consider the following security recommendations:
- Controlling network access to your instances is highly recommended. For example, configure your VPC and security groups appropriately. Learn more about controlling network traffic in the AWS documentation.
- Securely manage the credentials used to connect to your instances.
- Use our recommended Defense and Monitoring systems for your instances.
Step 4: API Co-Signer software installation
- Connect to your Co-Signer machine. Note the default username for the Amazon Linux EC2 instances is:
ec2-user
- If you access your server via SSH, run the following command:
ssh ec2-user@SERVER_IP
- On the Co-Signer machine:
- Enter root mode:
sudo -i
- In the Fireblocks Console, copy the AWS Nitro Co-Signer deployment package link from Settings > General.
- Download the Fireblocks AWS Nitro API co-signer deployment package directly from the Fireblocks Console or use the following command:
wget -O nitro-cosigner.tar.gz "<<download link>>"
- Extract the content by running the following command:
tar xvzf nitro-cosigner.tar.gz
-
Replace the default license file bundled in the deployment package (license.yaml) with the file you received from Fireblocks, which has your company name in it.
- Change the script's permissions to be executable:
chmod +x cosigner
- If you plan to set up a Co-Signer Callback Handler, place the TLS certificate of the Callback Handler in a file named certificate.pem in the same folder as the CLI script. This TLS certificate is verified by the Co-Signer on every call made to the Callback Handler. You can extract the TLS certificate from the terminal using the following command:
openssl s_client -connect <callback_handler_url>:443
- Run the API Co-Signer's setup:
./cosigner setup
- The CLI script will request you to enter the following inputs:
- KMS ARN: The CMK ARN that you created in step 2.
- Pairing Token: In the Fireblocks Console, go to Settings > Users. Find the API user, select the Pending Activation status, and then select More Actions > Copy Pairing Token. Remember, this token is only available for API users that are not currently paired with a signing device. The pairing token is valid for one hour after it is copied.
-
[Optional] Callback Handler URL: The HTTPS server base URL where the Co-Signer Callback Handler is available or will be available. If you don't have the callback handler URL available at this stage, you can provide it at a later stage as a configuration update.
- Enter the Callback URL. This is the HTTPS server base URL of the API Co-Signer Callback Handler.
Please enter callback URL (if using callback URL, else empty)
- The script will ask to select an authentication method:
Please select one of the callback authentication options: (1)-PUBLIC KEY (2)-certificate
- Recommended method: If you choose PUBLIC KEY, paste your public key and press return:
All callback handler requests should be authenticated. The following two options are available for authentication.
Public key authentication
This option is only available from version 1.1.4 and above. This is recommended for all new and upgraded instances. Read more about API Co-Signer version history.
This method uses a Signed JSON Web Token (JWT) for authentications. The POST request including the public key is sent as a JWT-encoded message.
Your callback handler endpoints should respond to requests that include a “/v2” prefix: <https://your_callback_base_url/v2/tx_sign_request>
The following steps output a private key used to authenticate your Callback Handler with your API Co-Signer. The public key is requested during API Co-Signer with Callback Handler installation in part three below.
- Generate a private key using the following command:
openssl genrsa -out private.pem 2048
Important
Fireblocks only supports RSA key 2048 bit for public key callback authentication.
- Export the public key from the previously generated private key using the following command:
openssl rsa -in private.pem -outform PEM -pubout -out public.pem
- You'll need to place a copy of the public key on your API Co-Signer server during the installation process below.
Authenticating Callback Handler requests from the API Co-Signer
The Callback Handler should authenticate each call it receives from your API Co-Signer to prevent attempts to sign requests from a malicious source.
Print the public key to include in your Callback Handler integration. This is required for the recommended authentication method.
Enter the following command after installing the API Co-Signer to extract the API Co-Signer public key:
./cosigner print-public-key
Learn more about Callback Handler code examples in our API documentation.
Certificate authentication
This option requires either a self-signed or CA-signed certificate. CA-signed certificates usually expire often and must be renewed. Renewing certificates requires re-enrolling the associated API user and restarting the API Co-Signer every renewal. This is no longer recommended and does not require generating a public key as described above.
TLS certificate authentication occurs during SSL negotiation, and the POST request is sent as plain text.
Your callback handler endpoints should respond to requests that do not include a “/v2” prefix: <https://your_callback_base_url/tx_sign_request>
Please paste your callback public key
- Generate a private key using the following command:
- If you choose a certificate, the script can either fetch the certificate from the Callback Handler URL, or you can paste the certificate.
Would you like to try to fetch the certificate for <URL> from the web server(y/n)?
- If you enter "n" to choose no, you will be requested to paste your certificate:
Need certificate for domain <URL domain>, please paste your certificate
- If you enter "n" to choose no, you will be requested to paste your certificate:
- Enter the Callback URL. This is the HTTPS server base URL of the API Co-Signer Callback Handler.
- Once the setup is completed, you will receive two values as an output - PCR4 and PCR8.
Going back to Step 2, take these values and save them in the KMS policy.
If this is not the first AWS Nitro Cosigner you are running, you only need to push the additional PCR4 value next to the existing ones. You don't need to override the existing PCR4 value.
The PCR8 value you receive from the installation should match the following:
da1d9eca20ce98ab4fdbc51f8e5a2307fd4c61829b7d8bff40976cd6676862c8f3476ff4bdd0f65ecf4a48d6eb3099a8
- Start the Co-Signer by running the following command:
./cosigner start
- If you're running the Co-Signer for the first time, the workspace Owner must approve a new MPC key shares request from the Fireblocks mobile app.
- Enter root mode:
If you do not plan on using a Callback Handler, your API Co-Signer should now be available.
Additional Features
Here are various use cases and commands for the Co-Signer.
Backup and Recovery
There are two important locations useful for backup and recovery purposes:
-
./fireblocks: The folder that was created for the API Co-Signer installation. Back up the folder to a tar.gz file by running:
./cosigner stop
cd /root
tar zcvf fireblocks.tar.gz fireblocks/ -
/databases/cosigner/backup: The backup folder maintained by the Co-Signer stores the backed-up secrets.db upon any change in the database. Run the following command in order to backup the databases folder into a tar.gz format:
tar zcvf databases.tar.gz /databases
Recovery on the same machine
Start the API Co-Signer once the machine has started:
sudo -i
cd fireblocks
./cosigner start
Deployment on a new server
There are two migration options:
- Within the new server, switch to root and go to the root folder:
sudo -i
cd /root - Copy the fireblocks.tar.gz file and untar it:
tar zxvf fireblocks.tar.gz
- Go to / and unzip the databases.tar.gz file there:
cd /
tar zxvf databases.tar.gz - Finish the migration by running:
./cosigner migrate-host
./cosigner start
If you receive a new PCR4 value, do not forget to add it to your KMS policy.
Adding additional API users
The API Co-Signer supports signing for multiple API users, either from the same workspace or different workspaces.
To add another user, run the following command that will request you to enter the following inputs:
./cosigner add-user
Configuration updates
Users can update the Callback Handler URL (callback_handler_url) by running:
./cosigner callback-update [user id]
The [user id] is optional and only needed if there are multiple API users paired with the same Co-Signer. When running the command in this instance, specify which user’s Callback Handler URL you want to update. You can retrieve a complete list of all users by running the following command:
./cosigner list-users
Software upgrades
Fireblocks notifies all customers when a software update is available. To update to a new API Co-Signer version, run the following command:
./cosigner upgrade-cosigner
If you receive a new PCR4 value, do not forget to add it to your KMS policy.
Status Check
You can check if the Cosigner is currently running using the following command:
./cosigner get-status
Powered by Anjuna
Anjuna specializes in running code in confidential computing environments. Fireblocks uses Anjuna's tools and capabilities to allow its customers to run the API Co-Signer in the AWS Nitro environment.