Quantum Ledger Database (QLDB) is Amazon Web Service’s commercial Ledger Database. Fundamentally a document storage database, it differentiates itself from other cloud-based document databases by integrating blockchain technology to offer an immutable transaction history and non-repudiation in the form of Merkle tree hash verification. It has other unique qualities, such as the ability to query it natively as if it were a relational database with the PartiQL language, the ability to stream its transaction records to other databases and services with Kinesis, and more.
This will be the first in a series of articles about the different options to secure the service. Today I am going to go over the built in controls AWS provides with the usual suspects of IAM, KMS, AWS PrivateLink, CloudWatch, CloudTrail and AWS Config.
I will be examining this through the lens of the security pillar of AWS’s Well Architected Framework with the following principals in mind:
Let’s get started!
The first area I want to dive into is IAM. As with every AWS deployment, you should ensure that you are using MFA to access your AWS accounts, and use IAM Roles with the principle of least privilege instead of IAM Users.
Let’s take a look at what policies AWS provides by default for QLDB, and some scenarios where they might be useful.
There aren’t many…
Description: Provides read only access to Amazon QLDB.
This built-in policy allows a principal to view Ledger details, journal export and stream details for all ledgers in the account. It also allows a principal to verify a document in the ledger. Note that this permission set does not provide the SendCommand
permission, so while you can do the verification, you will need to have the details (Document ID, Block address and Digest information) provided beforehand.
This is potentially a policy that can be provided to a service or user that does verification of documents, with the caveat that the verification process displays the PartiQL statement that created the document. This may surface some confidential information.
Additionally, this policy grants access to all ledgers, so it may be better, depending on your use case, to create a custom policy that is scoped to a specific ledger instead of “*”.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"qldb:ListLedgers",
"qldb:DescribeLedger",
"qldb:ListJournalS3Exports",
"qldb:ListJournalS3ExportsForLedger",
"qldb:DescribeJournalS3Export",
"qldb:DescribeJournalKinesisStream",
"qldb:ListJournalKinesisStreamsForLedger",
"qldb:GetBlock",
"qldb:GetDigest",
"qldb:GetRevision",
"qldb:ListTagsForResource"
],
"Resource": "*" <-- PSST! This really is not ideal if you don't need it
}
]
}
Description: Provides full access to Amazon QLDB via the service API.
This built-in policy allows a principal to perform most QLDB actions on any resource in an account. This is a very powerful policy and should be restricted to individuals in administrative roles or for exploratory purposes while first getting accustomed to QLDB in a sandbox or development environment.
One thing to note about this policy is that while it grants permissions to stream journals to Kinesis, it doesn’t provide any access to create the stream.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"qldb:CreateLedger",
"qldb:UpdateLedger",
"qldb:UpdateLedgerPermissionsMode",
"qldb:DeleteLedger",
"qldb:ListLedgers",
"qldb:DescribeLedger",
"qldb:ExportJournalToS3",
"qldb:ListJournalS3Exports",
"qldb:ListJournalS3ExportsForLedger",
"qldb:DescribeJournalS3Export",
"qldb:CancelJournalKinesisStream",
"qldb:DescribeJournalKinesisStream",
"qldb:ListJournalKinesisStreamsForLedger",
"qldb:StreamJournalToKinesis",
"qldb:GetDigest",
"qldb:GetRevision",
"qldb:GetBlock",
"qldb:TagResource",
"qldb:UntagResource",
"qldb:ListTagsForResource",
"qldb:SendCommand",
"qldb:PartiQLCreateTable",
"qldb:PartiQLCreateIndex",
"qldb:PartiQLDropTable",
"qldb:PartiQLDropIndex",
"qldb:PartiQLUndropTable",
"qldb:PartiQLDelete",
"qldb:PartiQLInsert",
"qldb:PartiQLUpdate",
"qldb:PartiQLSelect",
"qldb:PartiQLHistoryFunction",
"qldb:PartiQLRedact"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:PassedToService": "qldb.amazonaws.com"
}
}
}
]
}
Description: Provides full access to Amazon QLDB via the AWS Management Console.
This policy is identical to the AmazonQLDBFullAccess
policy with the added permissions of granting access to the Recent
and Saved
queries in the console. As such, the same recommendation applies here: only give this permission to administrators and for sandbox/exploratory purposes.
Like the previous policy, this also lacks the ability to create data streams.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"qldb:CreateLedger",
"qldb:UpdateLedger",
"qldb:UpdateLedgerPermissionsMode",
"qldb:DeleteLedger",
"qldb:ListLedgers",
"qldb:DescribeLedger",
"qldb:ExportJournalToS3",
"qldb:ListJournalS3Exports",
"qldb:ListJournalS3ExportsForLedger",
"qldb:DescribeJournalS3Export",
"qldb:CancelJournalKinesisStream",
"qldb:DescribeJournalKinesisStream",
"qldb:ListJournalKinesisStreamsForLedger",
"qldb:StreamJournalToKinesis",
"qldb:GetBlock",
"qldb:GetDigest",
"qldb:GetRevision",
"qldb:TagResource",
"qldb:UntagResource",
"qldb:ListTagsForResource",
"qldb:SendCommand",
"qldb:ExecuteStatement",
"qldb:ShowCatalog",
"qldb:InsertSampleData",
"qldb:PartiQLCreateTable",
"qldb:PartiQLCreateIndex",
"qldb:PartiQLDropTable",
"qldb:PartiQLDropIndex",
"qldb:PartiQLUndropTable",
"qldb:PartiQLDelete",
"qldb:PartiQLInsert",
"qldb:PartiQLUpdate",
"qldb:PartiQLSelect",
"qldb:PartiQLHistoryFunction",
"qldb:PartiQLRedact"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"dbqms:*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"kinesis:ListStreams",
"kinesis:DescribeStream"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:PassedToService": "qldb.amazonaws.com"
}
}
}
]
}
QLDB is integrated with KMS to allow you to encrypt your ledgers.
All data in Amazon QLDB is encrypted at rest by default with KMS and cannot be disabled.
On Ledger creation, you can choose an AWS owned key or a Customer Managed Key (CMK). After creation, you can freely swap between using an AWS owned key and a CMK. Server-side encryption is transparent, so this can be done at any time without the need to update the application.
Amazon QLDB only accepts HTTPS requests.
The way QLDB uses KMS will inform your key usage strategy and ledger design, so it’s important to keep in mind it’s limitations.
KMS keys can only be applied on a Ledger, not a Table. If you have multiple clients or use different customer managed KMS keys for different domains of your business, implement and maintain data segregation by creating separate ledgers for each key.
While you can’t apply a KMS key to a table, you can tag them. This can be combined with conditional policies on the IAM roles that access the tables to create a data classification layer of security.
For example, consider a situation where an IAM role necessarily has permission to the KMS key, but you don’t want the users of the role to access a protected table containing credit card information. While you could scope the IAM role permissions to exclude that specific table from the permissions policy, you could also create a data classification tag of confidential
on the credit card table and deny the role permissions to perform any QLDB actions on any tables tagged with the confidential
data classification. We will go more in depth on this concept in a later article.
If using a CMK, you will be required to add a key policy that grants permissions for the QLDB service to perform actions on the key. Below is an example key policy that will accomplish this.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid" : "Allow access to principals authorized to use Amazon QLDB",
"Effect" : "Allow",
"Principal" : {
"AWS" : "*"
},
"Action" : [
"kms:DescribeKey",
"kms:CreateGrant"
],
"Resource" : "arn:aws:kms:us-east-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab",
"Condition" : {
"StringEquals" : {
"kms:ViaService" : "qldb.us-east-1.amazonaws.com",
"kms:CallerAccount" : "111122223333"
}
}
}
]
}
If the ledger is encrypted with a CMK and that key is deleted, the ledger will be unrecoverable permanently.
Amazon QLDB can only be interacted with via API calls to the Amazon network. QLDB is a managed service, and as such the infrastructure and network security configuration options are limited.
The permissions mode that is configured on the Ledger determines the actions that an IAM principal can perform over the API. Amazon QLDB has two permissions modes:
ALLOW_ALL
and STANDARD
.
ALLOW_ALL
is a legacy permissions mode. It permits users with SendCommand
permissions to perform any PartiQL statements on any tables in the ledger that is specified by the permissions policy. It is not recommended to use this anymore as it’s an all or nothing setting with no option for granularity.
STANDARD
is a permissions mode that implicitly denies access to actions and tables in a ledger. It allows for granular access to ledgers, tables and PartiQL actions.
AWS PrivateLink endpoints are available for QLDB. This ensures that all traffic to QLDB is routed within the AWS network and allows any instances or services within your VPC that require access to QLDB to remain private.
The only supported API action through the endpoint is the SendCommand
and PartiQL statement actions. You cannot manage the control plane of the service through a PrivateLink interface endpoint.
FIPS endpoints are available for QLDB and have the same restrictions (can only use SendCommand
action) as regular PrivateLink endpoints. They are not widely available - see this link for details on which regions support regular and FIPS endpoints.
Using an endpoint policy, you control what actions can be sent to your QLDB Ledger through the endpoint. Combined with an IAM policy that forces actions on the Ledger to be performed via the endpoint, this is potentially a very powerful control mechanism - it allows for the ability to blanket permit or deny actions to all roles that use QLDB with one policy.
Below is an example of an endpoint policy that:
SendCommand
action through the endpoint to the specified ledger{
"Statement": [
{
"Sid": "QLDBSendCommandPermission",
"Principal": "*",
"Effect": "Allow",
"Action": "qldb:SendCommand",
"Resource": "arn:aws:qldb:us-east-1:123456789012:ledger/myExampleLedger"
},
{
"Sid": "QLDBPartiQLReadOnlyPermissions",
"Principal": "*",
"Effect": "Allow",
"Action": [
"qldb:PartiQLSelect",
"qldb:PartiQLHistoryFunction"
],
"Resource": [
"arn:aws:qldb:us-east-1:123456789012:ledger/myExampleLedger/table/*",
"arn:aws:qldb:us-east-1:123456789012:ledger/myExampleLedger/information_schema/user_tables"
]
}
]
}
Use CloudWatch to monitor database performance and use CloudTrail to record API calls made to your Ledgers. QLDB does not log transactional API calls to CloudTrail, so none of the PartiQL actions will appear in your CloudTrail logs. This means that to detect anomalous activity on your database, you will need to build some logic into your app.
AWS recommends the following metrics to monitor on a QLDB deployment:
As we can only monitor Ledger actions, you are limited to logging resource management tasks. Of these actions, the ones of concern for this article are the actions related to exporting of a Ledger’s journal. The journal contains the transactional history of the Ledger, and is very important to track all API calls that perform this to detect data exfiltration.
The actions are:
ExportJournalToS3
DescribeJournalS3Export
ListJournalS3ExportsForLedger
ListJournalS3Exports
AWS Config creates a resource for your ledger automatically. At the time of writing this article, there are no AWS Managed rules pertaining to QLDB.
QLDB is a fully managed service, and currently there is currently no built-in function to manually backup and restore your QLDB Ledgers. It is possible to export your Journal which can be imported to a new Ledger to create a copy, but it will be missing the original timestamps and not be a true backup of the original data.
So far we have discussed the built in options that AWS provides to secure QLDB:
Over the next few articles I will go in-depth on these topics. So check back often or follow Keep Secure’s twitter or linkedin profiles to get notified when my next article is released.
 
Tyler is an AWS Certified Solutions Architect and has over a decade of enterprise systems administration experience, bringing a wealth of knowledge on Windows, Linux and MacOS infrastructure. You can find him most days and nights trying to quench an insatiable thirst for knowledge of all things cloud and technology.