Uptycs Blog

Welcome! The Uptycs blog is for security professionals and osquery enthusiasts interested in exploring new ideas in cloud security. We hope you’ll enjoy our blog enough to subscribe and share.

Use cloudquery and osquery to simplify your cloud monitoring

With the shift toward cloud computing, many organizations have at least some footprint in the cloud. Thus it becomes important to secure both your on-prem and cloud infrastructure.

Cloudquery, which runs as an extension of osquery, simplifies the visualization and monitoring of all your cloud resources. It creates a seamless integration of cloud telemetry with the rest of your osquery-powered telemetry.

All cloud providers offer ways to secure your infrastructure, but under the shared responsibility model it’s the responsibility of you, the customer, to configure and set policies to secure your cloud resources and data. With hybrid environments, it’s a challenge even to visualize resources and understand their usage. You have to deal with different tools for on-prem environments and for cloud environments.

Cloudquery uses a familiar SQL interface. This removes the need to deploy and understand various cloud provider tools. Those who are already familiar with osquery can create scheduled queries to fetch the data related to their cloud deployments and send it to configured destinations.

Apart from this, osquery’s distributed query functionality can be used to query data in real time for ad-hoc analysis. Once you collect the data and store it in a database, there are numerous ways to apply the data:

  • Visualizations for various resources and their configurations
  • Trends/historical data analysis and identification of configuration drift
  • Detecting misconfigurations, such as S3 public buckets, and enablement of MFA for all users
  • Conformance to compliance standards like CIS Benchmarks for AWS, Azure, and GCP
  • Real-time investigation and root cause analysis
  • Overall security

For example, the following query will provide a list of all AWS EC2 instances across all configured AWS accounts. Note that there are numerous other parameters/columns providing the details related to each instance, but this sample query (and response) shows only a few for brevity.

Query and response showing a list of AWS EC2 instances.

Figure 1. Query and response showing a list of AWS EC2 instances. (Click to see larger version.)

Here’s a sample query that produces a list of public S3 buckets:

SELECT account_id, name FROM aws_s3_bucket where policy_status NOT LIKE '%"IsPublic":false%';

And finally, here’s a query that generates a list of instances with public IP addresses:

select account_id, region_code, instances_instance_id, instances_public_ip_address from aws_ec2_instance where instances_public_ip_address is not null AND instances_public_ip_address <> 'null';

Supported tables in cloudquery

Cloudquery supports various cloud providers and we will keep adding new tables frequently. The list of supported tables can be found here.

Cloudquery deployment

Cloudquery can be deployed as an osquery extension and as a Docker container. It can be deployed on-prem or in the cloud and can be configured to fetch data from one or more cloud providers. In a typical deployment you’ll have one instance of cloudquery in each cloud provider account. This makes data transfer faster and cheaper as the incoming data will not leave the perimeter of cloud deployment.

A typical cloudquery deployment.

Figure 2. A typical cloudquery deployment.

Detailed cloudquery deployment instructions are available through the following resources:

Osquery vs cloudquery

Cloudquery is an extension of osquery, not a replacement. You should install osquery on each endpoint to collect endpoint data and deploy cloudquery in each of your cloud environments to collect cloud data.

Configuring table schema

By default, we don’t flatten the JSON objects as it may result in an explosion of data and can incur heavy data transfer and storage costs. If required, the schema can be changed through configuration, though we strongly suggest that the flattening should be done close to the destination instead of at the source (in cloudquery).

These are the steps to change the schema of any table:

  • Change respective table_config.json file
  • Change the column list in respective Go code file
  • Recompile the code

Let's look at an example using the aws_ec2_egress_only_internet_gateway table. By default, this table has the following schema (aws/ec2/table_config.json):

"aws_ec2_egress_only_internet_gateway": {
   "aws": {
     "regionCodeAttribute": "region_code",
     "accountIdAttribute": "account_id"
   },
   "gcp": {},
   "azure": {},
   "parsedAttributes": [
     {
       "sourceName": "EgressOnlyInternetGateways_Attachments",
       "targetName": "attachments",
       "targetType": "TEXT",
       "enabled": true
     },
     {
       "sourceName": "EgressOnlyInternetGateways_Attachments_State",
       "targetName": "attachments_state",
       "targetType": "TEXT",
       "enabled": false
     },
     {
       "sourceName": "EgressOnlyInternetGateways_Attachments_VpcId",
       "targetName": "attachments_vpc_id",
       "targetType": "TEXT",
       "enabled": false
     },
     {
       "sourceName": "EgressOnlyInternetGateways_EgressOnlyInternetGatewayId",
       "targetName": "egress_only_internet_gateway_id",
       "targetType": "TEXT",
       "enabled": true
     },
     {
       "sourceName": "EgressOnlyInternetGateways_Tags",
       "targetName": "tags",
       "targetType": "TEXT",
       "enabled": true
     },
     {
       "sourceName": "EgressOnlyInternetGateways_Tags_Key",
       "targetName": "tags_key",
       "targetType": "TEXT",
       "enabled": false
     },
     {
       "sourceName": "EgressOnlyInternetGateways_Tags_Value",
       "targetName": "tags_value",
       "targetType": "TEXT",
       "enabled": false
     }
   ]
 }

With this configuration, the attachments column will be a JSON object including attachments_state and attachments_vpc_id. To have attachments_state and attachments_vpc_id as independent columns, we need to set the value of “enabled” for both of these columns to “true.”

The next step is to uncomment the attachments, attachments_state, and attachments_vpc_id column names in the code file (aws/ec2/aws_ec2_egress_only_internet_gateway.go):

// DescribeEgressOnlyInternetGatewaysColumns returns the list of columns in the table
func DescribeEgressOnlyInternetGatewaysColumns() []table.ColumnDefinition {
   return []table.ColumnDefinition{
       table.TextColumn("account_id"),
       table.TextColumn("region_code"),
       // table.TextColumn("attachments"),
       table.TextColumn("attachments_state"),
       table.TextColumn("attachments_vpc_id"),
       table.TextColumn("egress_only_internet_gateway_id"),
       table.TextColumn("tags"),
       //table.TextColumn("tags_key"),
       //table.TextColumn("tags_value"),
 
   }
}

After making these changes, you can rebuild the code and restart the extension with a new binary.

The future of cloudquery

There are lots of exciting features coming for cloudquery. PRs are welcome and appreciated. The following are some of the things planned (in no particular order):

  • New inventory tables for AWS, GCP, Azure
  • New tables for events (like AWS CloudTrail, AWS VPC Flow Logs)
  • Support for where clause

More to come

In the following video, Uma Reddy shares Uptycs’ vision for extending the capabilities of osquery to include cloud provider, container orchestrator, and SaaS provider data. These capabilities will let osquery offer inside-out and outside-in monitoring for hosts and containers.

 

Learn more and get started with cloudquery.