HashiCorp Nomad and Vault: Dynamic Secrets
In a cloud-native environment, secrets management is a critical aspect of security. HashiCorp Vault is a popular tool for managing secrets and protecting
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
.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.
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.
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.
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.
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.
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