Repository: turbot/steampipe-plugin-aws (language: go)

Issue:
Add table aws_mq_broker
**References**
https://pkg.go.dev/github.com/aws/aws-sdk-go-v2@v0.24.0/service/mq#Client.ListBrokersRequest



Discussion / hints:

Fix patch:
diff --git a/aws/plugin.go b/aws/plugin.go
index aa6c0217a..8a95d6d53 100644
--- a/aws/plugin.go
+++ b/aws/plugin.go
@@ -320,6 +320,7 @@ func Plugin(ctx context.Context) *plugin.Plugin {
 			"aws_macie2_classification_job":                                tableAwsMacie2ClassificationJob(ctx),
 			"aws_media_store_container":                                    tableAwsMediaStoreContainer(ctx),
 			"aws_mgn_application":                                          tableAwsMGNApplication(ctx),
+			"aws_mq_broker":                                                tableAwsMQBroker(ctx),
 			"aws_msk_cluster":                                              tableAwsMSKCluster(ctx),
 			"aws_msk_serverless_cluster":                                   tableAwsMSKServerlessCluster(ctx),
 			"aws_neptune_db_cluster":                                       tableAwsNeptuneDBCluster(ctx),
diff --git a/aws/service.go b/aws/service.go
index ea08815c2..2b5b04164 100644
--- a/aws/service.go
+++ b/aws/service.go
@@ -85,6 +85,7 @@ import (
 	"github.com/aws/aws-sdk-go-v2/service/macie2"
 	"github.com/aws/aws-sdk-go-v2/service/mediastore"
 	"github.com/aws/aws-sdk-go-v2/service/mgn"
+	"github.com/aws/aws-sdk-go-v2/service/mq"
 	"github.com/aws/aws-sdk-go-v2/service/neptune"
 	"github.com/aws/aws-sdk-go-v2/service/networkfirewall"
 	"github.com/aws/aws-sdk-go-v2/service/oam"
@@ -163,6 +164,7 @@ import (
 	macie2Endpoint "github.com/aws/aws-sdk-go/service/macie2"
 	mediastoreEndpoint "github.com/aws/aws-sdk-go/service/mediastore"
 	mgnEndpoint "github.com/aws/aws-sdk-go/service/mgn"
+	mqEndpoint "github.com/aws/aws-sdk-go/service/mq"
 	networkfirewallEndpoint "github.com/aws/aws-sdk-go/service/networkfirewall"
 	oamEndpoint "github.com/aws/aws-sdk-go/service/oam"
 	pinpointEndpoint "github.com/aws/aws-sdk-go/service/pinpoint"
@@ -939,6 +941,17 @@ func MGNClient(ctx context.Context, d *plugin.QueryData) (*mgn.Client, error) {
 	return mgn.NewFromConfig(*cfg), nil
 }
 
+func MQClient(ctx context.Context, d *plugin.QueryData) (*mq.Client, error) {
+	cfg, err := getClientForQuerySupportedRegion(ctx, d, mqEndpoint.EndpointsID)
+	if err != nil {
+		return nil, err
+	}
+	if cfg == nil {
+		return nil, nil
+	}
+	return mq.NewFromConfig(*cfg), nil
+}
+
 func NeptuneClient(ctx context.Context, d *plugin.QueryData) (*neptune.Client, error) {
 	cfg, err := getClientForQueryRegion(ctx, d)
 	if err != nil {
diff --git a/aws/table_aws_mq_broker.go b/aws/table_aws_mq_broker.go
new file mode 100644
index 000000000..77cf688f3
--- /dev/null
+++ b/aws/table_aws_mq_broker.go
@@ -0,0 +1,354 @@
+package aws
+
+import (
+	"context"
+
+	"github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/aws/aws-sdk-go-v2/service/mq"
+	"github.com/aws/aws-sdk-go-v2/service/mq/types"
+
+	mqv1 "github.com/aws/aws-sdk-go/service/mq"
+
+	"github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto"
+	"github.com/turbot/steampipe-plugin-sdk/v5/plugin"
+	"github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform"
+)
+
+//// TABLE DEFINITION
+
+func tableAwsMQBroker(_ context.Context) *plugin.Table {
+	return &plugin.Table{
+		Name:        "aws_mq_broker",
+		Description: "AWS MQ Broker",
+		Get: &plugin.GetConfig{
+			KeyColumns: plugin.SingleColumn("broker_id"),
+			Hydrate:    getMQBroker,
+			Tags:       map[string]string{"service": "mq", "action": "DescribeBroker"},
+			IgnoreConfig: &plugin.IgnoreConfig{
+				ShouldIgnoreErrorFunc: shouldIgnoreErrors([]string{"NotFoundException"}),
+			},
+		},
+		List: &plugin.ListConfig{
+			Hydrate: listMQBrokers,
+			Tags:    map[string]string{"service": "mq", "action": "ListBrokers"},
+		},
+		HydrateConfig: []plugin.HydrateConfig{
+			{
+				Func: getMQBroker,
+				Tags: map[string]string{"service": "mq", "action": "DescribeBroker"},
+			},
+		},
+		GetMatrixItemFunc: SupportedRegionMatrix(mqv1.EndpointsID),
+		Columns: awsRegionalColumns([]*plugin.Column{
+			{
+				Name:        "broker_name",
+				Description: "The broker's name.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "broker_id",
+				Description: "The unique ID that Amazon MQ generates for the broker.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "arn",
+				Description: "The Amazon Resource Name (ARN) of the broker.",
+				Type:        proto.ColumnType_STRING,
+				Transform:   transform.FromField("BrokerArn"),
+			},
+			{
+				Name:        "broker_state",
+				Description: "The broker's status.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "deployment_mode",
+				Description: "The broker's deployment mode.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "created",
+				Description: "The time when the broker was created.",
+				Type:        proto.ColumnType_TIMESTAMP,
+			},
+			{
+				Name:        "host_instance_type",
+				Description: "The broker's instance type.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "authentication_strategy",
+				Description: "The authentication strategy used to secure the broker. The default is SIMPLE.",
+				Type:        proto.ColumnType_STRING,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "data_replication_mode",
+				Description: "Describes whether this broker is a part of a data replication pair.",
+				Type:        proto.ColumnType_STRING,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "engine_type",
+				Description: "The type of broker engine. Currently, Amazon MQ supports ACTIVEMQ and RABBITMQ.",
+				Type:        proto.ColumnType_STRING,
+			},
+			{
+				Name:        "engine_version",
+				Description: "The broker engine's version.",
+				Type:        proto.ColumnType_STRING,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "pending_authentication_strategy",
+				Description: "The authentication strategy that will be applied when the broker is rebooted. The default is SIMPLE.",
+				Type:        proto.ColumnType_STRING,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "pending_data_replication_mode",
+				Description: "Describes whether this broker will be a part of a data replication pair after reboot.",
+				Type:        proto.ColumnType_STRING,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "pending_engine_version",
+				Description: "The broker engine version to upgrade to.",
+				Type:        proto.ColumnType_STRING,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "pending_host_instance_type",
+				Description: "The broker's host instance type to upgrade to.",
+				Type:        proto.ColumnType_STRING,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "publicly_accessible",
+				Description: "Enables connections from applications outside of the VPC that hosts the broker's subnets.",
+				Type:        proto.ColumnType_BOOL,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "storage_type",
+				Description: "The broker's storage type.",
+				Type:        proto.ColumnType_STRING,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "auto_minor_version_upgrade",
+				Description: "Enables automatic upgrades to new minor versions for brokers, as new versions are released and supported by Amazon MQ.",
+				Type:        proto.ColumnType_BOOL,
+				Hydrate:     getMQBroker,
+			},
+
+			// JSON columns
+			{
+				Name:        "actions_required",
+				Description: "Actions required for a broker.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "broker_instances",
+				Description: "A list of information about allocated brokers.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "configurations",
+				Description: "The list of all revisions for the specified configuration.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "data_replication_metadata",
+				Description: "The replication details of the data replication-enabled broker. Only returned if dataReplicationMode is set to CRDR.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "encryption_options",
+				Description: "Encryption options for the broker.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "ldap_server_metadata",
+				Description: "The metadata of the LDAP server used to authenticate and authorize connections to the broker.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "logs",
+				Description: "The list of information about logs currently enabled and pending to be deployed for the specified broker.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "pending_ldap_server_metadata",
+				Description: "The metadata of the LDAP server that will be used to authenticate and authorize connections to the broker after it is rebooted.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "maintenance_window_start_time",
+				Description: "The parameters that determine the WeeklyStartTime.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "pending_data_replication_metadata",
+				Description: "The pending replication details of the data replication-enabled broker. Only returned if pendingDataReplicationMode is set to CRDR.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "pending_security_groups",
+				Description: "The list of pending security groups to authorize connections to brokers.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "security_groups",
+				Description: "The list of rules (1 minimum, 125 maximum) that authorize connections to brokers.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "subnet_ids",
+				Description: "The list of groups that define which subnets and IP ranges the broker can use from different Availability Zones.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "users",
+				Description: "The list of all broker usernames for the specified broker.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+
+			// Steampipe standard columns
+			{
+				Name:        "tags",
+				Description: "A list of tags attached to the broker.",
+				Type:        proto.ColumnType_JSON,
+				Hydrate:     getMQBroker,
+			},
+			{
+				Name:        "title",
+				Description: resourceInterfaceDescription("title"),
+				Type:        proto.ColumnType_STRING,
+				Transform:   transform.FromField("BrokerName"),
+			},
+			{
+				Name:        "akas",
+				Description: resourceInterfaceDescription("akas"),
+				Type:        proto.ColumnType_JSON,
+				Transform:   transform.FromField("BrokerArn").Transform(transform.EnsureStringArray),
+			},
+		}),
+	}
+}
+
+//// LIST FUNCTION
+
+func listMQBrokers(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
+	logger := plugin.Logger(ctx)
+
+	// Create Session
+	svc, err := MQClient(ctx, d)
+	if err != nil {
+		logger.Error("aws_mq_broker.listMQBrokers", "service_creation_error", err)
+		return nil, err
+	}
+	if svc == nil {
+		// Unsupported region, return no data
+		return nil, nil
+	}
+
+	// Reduce the basic request limit down if the user has only requested a small number of rows
+	maxLimit := int32(100)
+	if d.QueryContext.Limit != nil {
+		limit := int32(*d.QueryContext.Limit)
+		if limit < maxLimit {
+			if limit < 5 {
+				maxLimit = 5
+			} else {
+				maxLimit = limit
+			}
+		}
+	}
+
+	input := mq.ListBrokersInput{
+		MaxResults: maxLimit,
+	}
+
+	paginator := mq.NewListBrokersPaginator(svc, &input, func(o *mq.ListBrokersPaginatorOptions) {
+		o.Limit = maxLimit
+		o.StopOnDuplicateToken = true
+	})
+
+	for paginator.HasMorePages() {
+		// apply rate limiting
+		d.WaitForListRateLimit(ctx)
+
+		output, err := paginator.NextPage(ctx)
+		if err != nil {
+			plugin.Logger(ctx).Error("aws_mq_broker.listMQBrokers", "api_error", err)
+			return nil, err
+		}
+
+		for _, broker := range output.BrokerSummaries {
+			d.StreamListItem(ctx, broker)
+
+			// Context may get cancelled due to manual cancellation or if the limit has been reached
+			if d.RowsRemaining(ctx) == 0 {
+				return nil, nil
+			}
+		}
+	}
+
+	return nil, nil
+}
+
+//// HYDRATE FUNCTIONS
+
+func getMQBroker(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
+	logger := plugin.Logger(ctx)
+
+	brokerId := ""
+	if h.Item != nil {
+		broker := h.Item.(types.BrokerSummary)
+		brokerId = *broker.BrokerId
+	} else {
+		brokerId = d.EqualsQualString("broker_id")
+	}
+	if brokerId == "" {
+		return nil, nil
+	}
+
+	// Create service
+	svc, err := MQClient(ctx, d)
+	if err != nil {
+		logger.Error("aws_mq_broker.getMQBroker", "service_creation_error", err)
+		return nil, err
+	}
+
+	// Unsupported region, return no data
+	if svc == nil {
+		return nil, nil
+	}
+
+	params := &mq.DescribeBrokerInput{
+		BrokerId: aws.String(brokerId),
+	}
+
+	op, err := svc.DescribeBroker(ctx, params)
+	if err != nil {
+		logger.Error("aws_mq_broker.getMQBroker", "api_error", err)
+		return nil, err
+	}
+
+	return op, nil
+}
\ No newline at end of file
diff --git a/docs/tables/aws_mq_broker.md b/docs/tables/aws_mq_broker.md
new file mode 100644
index 000000000..efb6f4636
--- /dev/null
+++ b/docs/tables/aws_mq_broker.md
@@ -0,0 +1,157 @@
+---
+title: "Steampipe Table: aws_mq_broker - Query AWS MQ Brokers using SQL"
+description: "Allows users to query AWS MQ Brokers."
+---
+
+# Table: aws_mq_broker - Query AWS MQ Brokers using SQL
+
+Amazon MQ is a managed message broker service provided by AWS (Amazon Web Services). It supports popular messaging protocols such as MQTT, AMQP, and STOMP, making it compatible with a variety of applications. Amazon MQ simplifies the setup, deployment, and maintenance of message brokers, allowing you to focus on developing your applications.
+
+## Table Usage Guide
+
+The `aws_mq_broker` table in Steampipe provides you with information about MQ brokers within AWS. This table allows you, as a DevOps engineer, to query broker specific details, including the boker ARN, creation time, and associated metadata. You can utilize this table to gather insights on nrokers, such as the number of broker nodes, the version and type of the engine used, the state of the broker, and more. The schema outlines the various attributes of the MQ broker for you, including the encryption info, authentication strategy, and associated tags.
+
+## Examples
+
+### Basic Info
+Explore the status and details of your AWS MQ broker to understand their configuration and operational state.
+
+```sql+postgres
+select
+  arn,
+  broker_name,
+  broker_state,
+  deployment_mode,
+  created,
+  host_instance_type,
+  engine_type,
+  engine_version
+  tags
+from
+  aws_mq_broker;
+```
+
+```sql+sqlite
+select
+  arn,
+  broker_name,
+  broker_state,
+  deployment_mode,
+  created,
+  host_instance_type,
+  engine_type,
+  engine_version
+  tags
+from
+  aws_mq_broker;
+```
+
+### List brokers that are in rebooting state
+Identify certain brokers within AWS MQ service that are in reboot state. This could be useful for system administrators who need to manage resources.
+
+```sql+postgres
+select
+  arn,
+  broker_name,
+  broker_state,
+  created
+  data_replication_mode,
+  authentication_strategy
+from
+  aws_mq_broker
+where
+  broker_state = 'REBOOT_IN_PROGRESS';
+```
+
+```sql+sqlite
+select
+  arn,
+  broker_name,
+  broker_state,
+  created
+  data_replication_mode,
+  authentication_strategy
+from
+  aws_mq_broker
+where
+  broker_state = 'REBOOT_IN_PROGRESS';
+```
+
+### List brokers that allow public access
+Determine the areas in which public access is allowed for broker. This is useful for identifying potential security risks and ensuring that access to sensitive data is appropriately restricted.
+
+```sql+postgres
+select
+  arn,
+  broker_name,
+  broker_state,
+  created
+from
+  aws_mq_broker
+where
+  publicly_accessible;
+```
+
+```sql+sqlite
+select
+  arn,
+  broker_name,
+  broker_state,
+  created
+from
+  aws_mq_broker
+where
+  publicly_accessible;
+```
+
+### List brokers that encrypted with customer managed key
+Identify the specific domains or components within the system where data is secured through encryption using keys managed by the customer.
+
+```sql+postgres
+select
+  arn,
+  broker_name,
+  encryption_options ->> 'UseAwsOwnedKey' as use_aws_owned_key,
+  created
+from
+  aws_mq_broker
+where
+  encryption_options ->> 'UseAwsOwnedKey' = 'false';
+```
+
+```sql+sqlite
+select
+  arn,
+  broker_name,
+  json_extract(encryption_options, '$.EncryptionInfo.EncryptionAtRest') as use_aws_owned_key,
+  created
+from
+  aws_mq_broker
+where
+  json_extract(encryption_options, '$.UseAwsOwnedKey') = 'false';
+```
+
+### Get maintenance window details of brokers
+During the Maintenance Window, the broker instances might be briefly unavailable or experience reduced capacity as updates are applied. This scheduled approach helps minimize the impact on your applications and users, as these activities are carried out during a designated time frame, allowing for predictability and coordination.
+
+```sql+postgres
+select
+  arn,
+  broker_name,
+  maintenance_window_start_time -> 'DayOfWeek' as day_of_week,
+  maintenance_window_start_time -> 'TimeOfDay' as time_of_day,
+  maintenance_window_start_time -> 'TimeZone' as time_zone
+from
+  aws_mq_broker;
+```
+
+```sql+sqlite
+select
+  arn,
+  broker_name,
+  json_extract(maintenance_window_start_time, '$.DayOfWeek') as day_of_week,
+  json_extract(maintenance_window_start_time, '$.TimeOfDay') as time_of_day,
+  json_extract(maintenance_window_start_time, '$.TimeZone') as time_zone
+from
+  aws_mq_broker;
+```
\ No newline at end of file
diff --git a/go.mod b/go.mod
index d1e6f8a07..99197dcb1 100644
--- a/go.mod
+++ b/go.mod
@@ -78,6 +78,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/service/macie2 v1.26.0
 	github.com/aws/aws-sdk-go-v2/service/mediastore v1.13.0
 	github.com/aws/aws-sdk-go-v2/service/mgn v1.17.0
+	github.com/aws/aws-sdk-go-v2/service/mq v1.16.5
 	github.com/aws/aws-sdk-go-v2/service/neptune v1.19.1
 	github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.24.0
 	github.com/aws/aws-sdk-go-v2/service/oam v1.1.1
@@ -119,7 +120,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/service/wafv2 v1.24.2
 	github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.20.1
 	github.com/aws/aws-sdk-go-v2/service/workspaces v1.28.0
-	github.com/aws/smithy-go v1.14.2
+	github.com/aws/smithy-go v1.19.0
 	github.com/gocarina/gocsv v0.0.0-20201208093247-67c824bc04d4
 	github.com/golang/protobuf v1.5.3
 	github.com/turbot/go-kit v0.9.0-rc.1
diff --git a/go.sum b/go.sum
index d1091840d..6686edff1 100644
--- a/go.sum
+++ b/go.sum
@@ -395,6 +395,8 @@ github.com/aws/aws-sdk-go-v2/service/mediastore v1.13.0 h1:rxJYsWs815NAgRTzWe//9
 github.com/aws/aws-sdk-go-v2/service/mediastore v1.13.0/go.mod h1:W3pI4V/pFD8Nttvxa9vSwifjgdOxa+EgwNUOVDYjB0c=
 github.com/aws/aws-sdk-go-v2/service/mgn v1.17.0 h1:q6YOP0qCkyT1F2nbCYLc2oykdturUutgfGdFOVlxRbI=
 github.com/aws/aws-sdk-go-v2/service/mgn v1.17.0/go.mod h1:up+ZyvBjd1NjSYXErQqLUMYbrZsqt1e6uIl5Kx3qrwQ=
+github.com/aws/aws-sdk-go-v2/service/mq v1.16.5 h1:xlziZnBjo10pGC+Uol5j8JNSzQksYOgHzAmF5sKnE/s=
+github.com/aws/aws-sdk-go-v2/service/mq v1.16.5/go.mod h1:kxETQ9R0dWsvWyL+5Vp/pNsEYejv76B+RvHr3S0jjhI=
 github.com/aws/aws-sdk-go-v2/service/neptune v1.19.1 h1:0ssNLA0sY0usb/mOM1mESth84upUZejPwo47rP12yj0=
 github.com/aws/aws-sdk-go-v2/service/neptune v1.19.1/go.mod h1:kBudc/ZVbpqaZmWaZiQgyujuCgsPqh6kYlzGeW65wh4=
 github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.24.0 h1:BHc8oItUVd0/RfgQLeRenPcNUWNi6o7g/9bLQK5kLns=
@@ -482,8 +484,9 @@ github.com/aws/aws-sdk-go-v2/service/wellarchitected v1.20.1/go.mod h1:Hb9paYQ+u
 github.com/aws/aws-sdk-go-v2/service/workspaces v1.28.0 h1:sjfoG4ahd0yE77sKiBokTlZHd9pk1k+vPGNJo6ct2QQ=
 github.com/aws/aws-sdk-go-v2/service/workspaces v1.28.0/go.mod h1:oudvE1/KOdqMDrq9PG1QjLpvQb8S5R3y2Fci+Vuc6To=
 github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
-github.com/aws/smithy-go v1.14.2 h1:MJU9hqBGbvWZdApzpvoF2WAIJDbtjK2NDJSiJP7HblQ=
 github.com/aws/smithy-go v1.14.2/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
+github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM=
+github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=


Test patch:
diff --git a/aws-test/tests/aws_mq_broker/test-get-expected.json b/aws-test/tests/aws_mq_broker/test-get-expected.json
new file mode 100644
index 000000000..af9d8d238
--- /dev/null
+++ b/aws-test/tests/aws_mq_broker/test-get-expected.json
@@ -0,0 +1,7 @@
+[
+  {
+    "arn": "{{ output.resource_arn.value }}",
+    "broker_id": "{{ output.resource_id.value }}",
+    "broker_name": "{{ resourceName }}"
+  }
+]
diff --git a/aws-test/tests/aws_mq_broker/test-get-query.sql b/aws-test/tests/aws_mq_broker/test-get-query.sql
new file mode 100644
index 000000000..df2359b65
--- /dev/null
+++ b/aws-test/tests/aws_mq_broker/test-get-query.sql
@@ -0,0 +1,3 @@
+select arn, broker_name, broker_id
+from aws.aws_mq_broker
+where broker_id = '{{ output.resource_id.value }}';
diff --git a/aws-test/tests/aws_mq_broker/test-list-expected.json b/aws-test/tests/aws_mq_broker/test-list-expected.json
new file mode 100644
index 000000000..9432ccc81
--- /dev/null
+++ b/aws-test/tests/aws_mq_broker/test-list-expected.json
@@ -0,0 +1,8 @@
+[
+  {
+    "arn": "{{ output.resource_arn.value }}",
+    "broker_name": "{{ resourceName }}",
+    "engine_type": "{{ output.engine_type.value }}",
+    "engine_version": "{{ output.engine_version.value }}"
+  }
+]
diff --git a/aws-test/tests/aws_mq_broker/test-list-query.sql b/aws-test/tests/aws_mq_broker/test-list-query.sql
new file mode 100644
index 000000000..9f4e642e5
--- /dev/null
+++ b/aws-test/tests/aws_mq_broker/test-list-query.sql
@@ -0,0 +1,3 @@
+select arn, engine_type, engine_version, broker_name
+from aws.aws_mq_broker
+where broker_name = '{{ resourceName }}';
diff --git a/aws-test/tests/aws_mq_broker/test-not-found-expected.json b/aws-test/tests/aws_mq_broker/test-not-found-expected.json
new file mode 100644
index 000000000..fe51488c7
--- /dev/null
+++ b/aws-test/tests/aws_mq_broker/test-not-found-expected.json
@@ -0,0 +1,1 @@
+[]
diff --git a/aws-test/tests/aws_mq_broker/test-not-found-query.sql b/aws-test/tests/aws_mq_broker/test-not-found-query.sql
new file mode 100644
index 000000000..6c06ac166
--- /dev/null
+++ b/aws-test/tests/aws_mq_broker/test-not-found-query.sql
@@ -0,0 +1,3 @@
+select account_id, akas, region, tags, title
+from aws.aws_mq_broker
+where broker_name = 'dummy';
diff --git a/aws-test/tests/aws_mq_broker/test-turbot-expected.json b/aws-test/tests/aws_mq_broker/test-turbot-expected.json
new file mode 100644
index 000000000..25f248de4
--- /dev/null
+++ b/aws-test/tests/aws_mq_broker/test-turbot-expected.json
@@ -0,0 +1,13 @@
+[
+  {
+    "akas": [
+      "{{ output.resource_arn.value }}"
+    ],
+    "broker_name": "{{ resourceName }}",
+    "region": "{{ output.aws_region.value }}",
+    "tags": {
+      "Name": "{{ resourceName }}"
+    },
+    "title": "{{ resourceName }}"
+  }
+]
diff --git a/aws-test/tests/aws_mq_broker/test-turbot-query.sql b/aws-test/tests/aws_mq_broker/test-turbot-query.sql
new file mode 100644
index 000000000..6af1d61c9
--- /dev/null
+++ b/aws-test/tests/aws_mq_broker/test-turbot-query.sql
@@ -0,0 +1,3 @@
+select akas, broker_name, region, tags, title
+from aws.aws_mq_broker
+where broker_name = '{{ resourceName }}';
diff --git a/aws-test/tests/aws_mq_broker/variables.json b/aws-test/tests/aws_mq_broker/variables.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/aws-test/tests/aws_mq_broker/variables.json
@@ -0,0 +1,1 @@
+{}
diff --git a/aws-test/tests/aws_mq_broker/variables.tf b/aws-test/tests/aws_mq_broker/variables.tf
new file mode 100644
index 000000000..0e3ef0165
--- /dev/null
+++ b/aws-test/tests/aws_mq_broker/variables.tf
@@ -0,0 +1,149 @@
+
+variable "resource_name" {
+  type        = string
+  default     = "turbot-test-20200125-create-update"
+  description = "Name of the resource used throughout the test."
+}
+
+variable "aws_profile" {
+  type        = string
+  default     = "default"
+  description = "AWS credentials profile used for the test. Default is to use the default profile."
+}
+
+variable "aws_region" {
+  type        = string
+  default     = "us-east-1"
+  description = "AWS region used for the test. Does not work with default region in config, so must be defined here."
+}
+
+variable "aws_region_alternate" {
+  type        = string
+  default     = "us-east-2"
+  description = "Alternate AWS region used for tests that require two regions (e.g. DynamoDB global tables)."
+}
+
+provider "aws" {
+  profile = var.aws_profile
+  region  = var.aws_region
+}
+
+provider "aws" {
+  alias   = "alternate"
+  profile = var.aws_profile
+  region  = var.aws_region_alternate
+}
+
+data "aws_partition" "current" {}
+data "aws_caller_identity" "current" {}
+data "aws_region" "primary" {}
+data "aws_region" "alternate" {
+  provider = aws.alternate
+}
+
+data "null_data_source" "resource" {
+  inputs = {
+    scope = "arn:${data.aws_partition.current.partition}:::${data.aws_caller_identity.current.account_id}"
+  }
+}
+
+resource "aws_mq_configuration" "named_test_resource" {
+  description    = "Example Configuration"
+  name           = var.resource_name
+  engine_type    = "ActiveMQ"
+  engine_version = "5.17.6"
+
+  data = <<DATA
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<broker xmlns="http://activemq.apache.org/schema/core">
+  <plugins>
+    <forcePersistencyModeBrokerPlugin persistenceFlag="true"/>
+    <statisticsBrokerPlugin/>
+    <timeStampingBrokerPlugin ttlCeiling="86400000" zeroExpirationOverride="86400000"/>
+  </plugins>
+</broker>
+DATA
+}
+
+resource "aws_vpc" "main" {
+  cidr_block = "10.0.0.0/16"
+  tags = {
+    name = var.resource_name
+  }
+}
+
+resource "aws_security_group" "named_test_resource" {
+  vpc_id      = aws_vpc.main.id
+  name        = var.resource_name
+  description = "Test Security Group."
+  tags = {
+    name = var.resource_name
+  }
+}
+
+resource "aws_subnet" "named_test_resource" {
+  vpc_id     = aws_vpc.main.id
+  cidr_block = "10.0.1.0/24"
+  tags = {
+    Name = var.resource_name
+  }
+}
+
+resource "aws_mq_broker" "named_test_resource" {
+  depends_on  = [aws_subnet.named_test_resource, aws_security_group.named_test_resource, aws_vpc.main, aws_mq_configuration.named_test_resource]
+  broker_name = var.resource_name
+
+  configuration {
+    id       = aws_mq_configuration.named_test_resource.id
+    revision = aws_mq_configuration.named_test_resource.latest_revision
+  }
+
+  engine_type        = "ActiveMQ"
+  engine_version     = "5.17.6"
+  host_instance_type = "mq.t2.micro"
+  security_groups    = [aws_security_group.named_test_resource.id]
+  subnet_ids = [aws_subnet.named_test_resource.id]
+
+  user {
+    username = "ExampleUser"
+    password = "MindTheGapGood"
+  }
+
+  tags = {
+    Name = var.resource_name
+  }
+}
+
+output "account_id" {
+  value = data.aws_caller_identity.current.account_id
+}
+
+output "aws_region" {
+  value = data.aws_region.primary.name
+}
+
+output "aws_partition" {
+  value = data.aws_partition.current.partition
+}
+
+output "resource_arn" {
+  depends_on  = [aws_mq_broker.named_test_resource]
+  value       = aws_mq_broker.named_test_resource.arn
+}
+
+output "resource_id" {
+  depends_on  = [aws_mq_broker.named_test_resource]
+  value       = aws_mq_broker.named_test_resource.id
+}
+
+output "engine_type" {
+  value = "ActiveMQ"
+}
+
+output "engine_version" {
+  value = "5.17.6"
+}
+
+output "resource_name" {
+  value = var.resource_name
+}