Leveraging Terraform for Enhanced Asset Security with Mondoo - Part 2: Data Sources


Bicycle

As organizations strive to safeguard their digital assets, innovative solutions like Mondoo have emerged to enhance security and compliance across various infrastructures. In our previous blog, we introduced Mondoo and explored its integration with Terraform to automate the deployment of secure and compliant environments. Today, we dive into the crucial aspect of data sources in Terraform and how Mondoo's capabilities can be leveraged to ensure robust infrastructure management.

What are Data Sources in Terraform?

In Terraform, a data source allows you to fetch read-only information that can be used for configuring or managing resources. Data sources are vital for referencing existing infrastructure components or gathering information about resources that cannot be directly managed by Terraform. By using data sources, you can dynamically configure resources based on the real-time state of your infrastructure, ensuring that your configurations are always up-to-date and accurate.

Mondoo's Data Sources

As of July 2024, due to our cooperation with the Mondoo Team, the Mondoo Terraform Provider offers five valuable data sources that enhance security and compliance checks within your infrastructure. Let's explore these data sources in detail and understand how they can be utilized effectively.

mondoo_organization

The mondoo_organization data source enables you to retrieve information about a specific organization within Mondoo. Organizations provide a way to group spaces together and manage team members and access.

Example Usage:

1data "mondoo_organization" "org" {
2  id = "your-org-1234567"
3}
4
5output "org_mrn" {
6  description = "MRN of the organization"
7  value       = data.mondoo_organization.org.mrn
8}

Here, we fetch details about an organization with the ID your-org-1234567 and output its MRN.

mondoo_space

The mondoo_space data source allows you to fetch details about a specific space in Mondoo. Spaces live within organizations and contain Mondoo's integrations, policies and frameworks.

Example Usage:

1data "mondoo_space" "space" {
2  id = "your-space-1234567"
3}
4
5output "space_name" {
6  description = "The name of the space"
7  value       = data.mondoo_space.space.name
8}

In this example, we fetch details about a space with the ID your-space-1234567 and output its name.

mondoo_assets

The mondoo_assets data source allows you to retrieve information about all assets within a Mondoo space. This is particularly useful for gathering details about assets such as virtual machines, databases, or cloud resources that are subject to continuous security assessments and compliance checks.

Example Usage:

1data "mondoo_assets" "assets_data" {
2  space_id = "my-space-1234567"
3}
4
5output "asset_mrns" {
6    value       = [for asset in data.mondoo_assets.assets_data.assets : asset.mrn]
7    description = "MRNs of the assets"
8}

In this example, we fetch details about all assets within the space with the ID my-space-1234567 and output the MRNs. This can be useful for dynamically configuring other resources based on the state of these asset.

mondoo_policies

The mondoo_policies data source enables you to retrieve information about the security policies defined in a Mondoo space. This is essential for ensuring that your infrastructure adheres to the required security standards and compliance guidelines.

Example Usage:

 1data "mondoo_policies" "policies_data" {
 2  space_id      = "your-space-1234567"
 3  catalog_type  = "ALL" # available options: "ALL", "POLICY", "QUERYPACK"
 4  assigned_only = true
 5}
 6
 7output "policies_mrn" {
 8  value       = [for policy in data.mondoo_policies.policies_data.policies : policy.policy_mrn]
 9  description = "The MRN of the policies in the space according to the filter criteria."
10}

Here, we retrieve details about all assigned policies within the space with the ID your-space-1234567 and output the MRNs. This can help you ensure that the correct policies have been set within a space.

mondoo_frameworks

The mondoo_frameworks data source allows you to retrieve information about the compliance frameworks defined in a Mondoo space. Frameworks allow an organizations to manage and increase its compliance with frameworks like ISO/IEC 27001:2022 and many more.

Example Usage:

1data "mondoo_frameworks" "frameworks_data" {
2  space_id = "your-space-1234567"
3}
4
5output "framework_mrn" {
6  value       = [for framework in data.mondoo_frameworks.frameworks_data.frameworks : framework.mrn]
7  description = "The MRN of the frameworks in the space."
8}

This configuration fetches and displays the MRNs of all frameworks in the specified space your-space-1234567, helping to view and manage compliance frameworks effectively.

Example: Dynamic Configuration Based on Policy Data Source

Let's consider an example where we dynamically enable all policies, in a newly created space, which have previously been disabled, based on the results of the mondoo_policies data source.

 1provider "mondoo" {
 2  region = "eu"
 3}
 4
 5resource "mondoo_space" "my_space" {
 6  name   = "My Space Name"
 7  org_id = "your-org-1234567"
 8}
 9
10data "mondoo_policies" "policies_data" {
11  space_id      = mondoo_space.my_space.id
12  catalog_type  = "ALL" # available options: "ALL", "POLICY", "QUERYPACK"
13  assigned_only = false
14}
15
16locals {
17  policies_mrn = [for policy in data.mondoo_policies.policies_data.policies : policy.policy_mrn]
18}
19
20resource "mondoo_policy_assignment" "space" {
21  space_id = mondoo_space.my_space.id
22
23  policies = local.policies_mrn
24
25  state = "enabled" # default is enabled, we also support preview and disabled
26
27  depends_on = [
28    mondoo_space.my_space
29  ]
30}

In this example, we use the mondoo_policies data source to fetch the latest security scan results. We then use the mondoo_policy_assignment resource to activate all disabled policies. In this way we can ensure that all policies are active no matter what.

Discovering How to Build Terraform Provider Data Sources

As mentioned above, we at Infralovers, in collaboration with the Mondoo Team, have been working on expanding the Mondoo Terraform Provider capabilities. We have vastly expanded our knowledge regarding the development of Terraform providers. In this blog of the series, we would like to share our knowledge regarding the development of Data Sources for Mondoo using the Terraform Provider Framework.

Mondoo uses the terraform-plugin-codegen-framework allowing for an easy and consistent expansion of their Terraform Provider. The code below showcases the bare-bones structure of such a data source, which we will discuss in detail. The following paragraphs will showcase the different code and building blocks of a data source.

Packages and Imports

1package provider
2
3import (
4    "context"
5
6    "github.com/hashicorp/terraform-plugin-framework/datasource"
7    "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
8    "github.com/hashicorp/terraform-plugin-framework/types"
9)

Like in every Go code, the first thing we typically do is to define the package name, followed by importing the necessary packages and dependencies that the code will use. Here, essential imports include context for managing request contexts, and several packages from the Terraform Plugin Framework, which are important for defining data sources and their schemas in a Terraform provider.

Type Declarations

 1var _ datasource.DataSource = (*testDataSource)(nil)
 2
 3func NewTestDataSource() datasource.DataSource {
 4    return &testDataSource{}
 5}
 6
 7type testDataSource struct{}
 8
 9type testDataSourceModel struct {
10    Id types.String `tfsdk:"id"`
11}

The provided Go code defines a Terraform data source for a provider using the HashiCorp Terraform Plugin Framework. The data source is named testDataSource, and it implements the datasource.DataSource interface. This interface requires several functions to manage the lifecycle of the data source: Metadata, Schema, and Read.

We need to define the following types before starting to implement data source lifecycle logic:

  • testDataSource: This is an empty struct that serves as the receiver for the data source function. During our development of the Mondoo Provider, we would use this struct to declare the client API, which in Mondoo’s case was a GraphQL API. This would later allow us to call on this client to make GraphQL requests.
  • testDataSourceModel: This struct defines the schema for the data source, containing, for example, an Id field of type types.String. Notice that the struct adds a tfsdk:"id" to the Id field. This tells Terraform that the data source can have a field called id.

Metadata Function

1func (d *testDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
2    resp.TypeName = req.ProviderTypeName + "_test"
3}

The Metadata function sets the data source type name by appending _test to the provider type name. This helps Terraform identify the data source type.

Schema Function

1func (d *testDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
2    resp.Schema = schema.Schema{
3        Attributes: map[string]schema.Attribute{
4            "id": schema.StringAttribute{
5                Computed: true,
6            },
7        },
8    }
9}

The Schema function defines the schema for the data source. It specifies that the data source has an id attribute, which is a computed string. This means the id can be generated by the provider and does not need to be supplied by the user.

Read Function

 1func (d *testDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
 2    var data testDataSourceModel
 3
 4    // Read Terraform configuration data into the model
 5    resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
 6
 7    if resp.Diagnostics.HasError() {
 8        return
 9    }
10
11    // Read API call logic
12
13    // Example data value setting
14    data.Id = types.StringValue("example-id")
15
16    // Save data into Terraform state
17    resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
18}

The Read function fetches the data from the external API or service and updates the Terraform state. Here, we read the configuration data into our testDataSourceModel and set the id attribute. In the Read function, we typically make an API call to fetch the necessary data. For the sake of this example, we set the id attribute to a placeholder value "example-id". In a real implementation, you would replace this with actual data fetched from Mondoo or another service.

Code Summary

The code provides a basic implementation of a Terraform data source using the HashiCorp Terraform Plugin Framework. It includes functions for managing the data source's lifecycle: Metadata, Schema, and Read. The schema is defined with a single computed id attribute. The actual API call logic for fetching data is not implemented and would need to be added where indicated by comments. The Read function sets a placeholder value for the id attribute, which should be replaced with real data from an external API.

Conclusion

Data sources in Terraform are powerful tools for dynamically configuring and managing infrastructure based on real-time information. Mondoo's data sources enhance this capability by providing detailed insights into organizations, spaces, policies and assets. By leveraging these data sources, you can ensure that your infrastructure remains secure and compliant with the latest standards and guidelines.

In our next blog post, we will delve into the process of importing existing resources into Terraform. Stay tuned to learn more about harnessing the full potential of Mondoo and Terraform for robust infrastructure security and compliance.

Go Back explore our courses

We are here for you

You are interested in our courses or you simply have a question that needs answering? You can contact us at anytime! We will do our best to answer all your questions.

Contact us