Skip to content

Conversation

rakeshclouddevops
Copy link
Contributor

No description provided.

@github-advanced-security
Copy link

This pull request sets up GitHub code scanning for this repository. Once the scans have completed and the checks have passed, the analysis results for this pull request branch will appear on this overview. Once you merge this pull request, the 'Security' tab will show more code scanning analysis results (for example, for the default branch). Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results. For more information about GitHub code scanning, check out the documentation.

Comment on lines +66 to +71
resource "aws_secretsmanager_secret" "mq_master_username_secret" {
count = var.use_secrets_manager && var.mq_admin_user != "" ? 1 : 0
name = "${var.secret_manager_key_prefix}/admin/username"
description = "MQ Admin Username"
tags = var.tags
}

Check notice

Code scanning / defsec

Secrets Manager should use customer managed keys Note

Secret explicitly uses the default key.
Comment on lines +98 to +103
resource "aws_secretsmanager_secret" "mq_application_username_secret" {
count = var.use_secrets_manager && var.mq_application_user != "" ? 1 : 0
name = "${var.secret_manager_key_prefix}/application/username"
description = "AMQ Application Username"
tags = var.tags
}

Check notice

Code scanning / defsec

Secrets Manager should use customer managed keys Note

Secret explicitly uses the default key.
Comment on lines +206 to +211
resource "aws_cloudwatch_log_group" "mq_logs" {
count = var.enable_cloudwatch_logs ? 1 : 0
name = "/aws/mq/${var.mq_broker_name}"
retention_in_days = var.cloudwatch_log_retention_days
tags = var.tags
}

Check notice

Code scanning / defsec

CloudWatch log groups should be encrypted using CMK Note

Log group is not encrypted.
main.tf Outdated
Comment on lines 214 to 288
resource "aws_mq_broker" "default" {
count = var.mq_broker_name != "" ? 1 : 0
broker_name = var.mq_broker_name
deployment_mode = var.deployment_mode
engine_type = var.engine_type
engine_version = var.engine_version
host_instance_type = var.host_instance_type
auto_minor_version_upgrade = var.auto_minor_version_upgrade
apply_immediately = var.apply_immediately
publicly_accessible = var.publicly_accessible
subnet_ids = var.subnet_ids
tags = var.tags
# security_groups = [module.security_group.security_group_id]
security_groups = var.security_group_id

# Encryption options - Use AWS-owned KMS key or a custom key
dynamic "encryption_options" {
for_each = var.encryption_enabled ? ["true"] : []
content {
kms_key_id = module.kms.key_id
use_aws_owned_key = false
}
}

# Enable CloudWatch logs for general and audit logs if CloudWatch is enabled
logs {
general = var.general_log_enabled ? true : false
audit = var.audit_log_enabled ? true : false
}

maintenance_window_start_time {
day_of_week = var.maintenance_day_of_week
time_of_day = var.maintenance_time_of_day
time_zone = var.maintenance_time_zone
}

# Dynamically assign the user based on whether admin or application user exists
dynamic "user" {
for_each = length(var.mq_admin_user) > 0 || length(var.mq_application_user) > 0 ? [1] : []

content {
username = length(var.mq_admin_user) > 0 ? (
var.use_secrets_manager ? (
length(aws_secretsmanager_secret.mq_master_username_secret) > 0 ? jsondecode(aws_secretsmanager_secret_version.mq_master_username_version[0].secret_string).username : "default_admin_user"
) : (
length(data.aws_ssm_parameter.mq_master_username) > 0 ? data.aws_ssm_parameter.mq_master_username[0].value : "default_admin_user"
)
) : (
var.use_secrets_manager ? (
length(aws_secretsmanager_secret.mq_application_username_secret) > 0 ? jsondecode(aws_secretsmanager_secret_version.mq_application_username_version[0].secret_string).username : "default_application_user"
) : (
length(data.aws_ssm_parameter.mq_application_username) > 0 ? data.aws_ssm_parameter.mq_application_username[0].value : "default_application_user"
)
)

password = length(var.mq_admin_password) > 0 ? (
var.use_secrets_manager ? (
length(aws_secretsmanager_secret.mq_master_password_secret) > 0 ? jsondecode(aws_secretsmanager_secret_version.mq_master_password_version[0].secret_string).password : "Admin12345678!"
) : (
length(data.aws_ssm_parameter.mq_master_password) > 0 ? data.aws_ssm_parameter.mq_master_password[0].value : "Admin12345678!"
)
) : (
var.use_secrets_manager ? (
length(aws_secretsmanager_secret.mq_application_password_secret) > 0 ? jsondecode(aws_secretsmanager_secret_version.mq_application_password_version[0].secret_string).password : "App12345678!"
) : (
length(data.aws_ssm_parameter.mq_application_password) > 0 ? data.aws_ssm_parameter.mq_application_password[0].value : "App12345678!"
)
)

groups = var.mq_admin_groups
console_access = var.console_access
}
}

}

Check warning

Code scanning / defsec

MQ Broker should have audit logging enabled Warning

Broker does not have audit logging enabled.
main.tf Outdated
Comment on lines 214 to 288
resource "aws_mq_broker" "default" {
count = var.mq_broker_name != "" ? 1 : 0
broker_name = var.mq_broker_name
deployment_mode = var.deployment_mode
engine_type = var.engine_type
engine_version = var.engine_version
host_instance_type = var.host_instance_type
auto_minor_version_upgrade = var.auto_minor_version_upgrade
apply_immediately = var.apply_immediately
publicly_accessible = var.publicly_accessible
subnet_ids = var.subnet_ids
tags = var.tags
# security_groups = [module.security_group.security_group_id]
security_groups = var.security_group_id

# Encryption options - Use AWS-owned KMS key or a custom key
dynamic "encryption_options" {
for_each = var.encryption_enabled ? ["true"] : []
content {
kms_key_id = module.kms.key_id
use_aws_owned_key = false
}
}

# Enable CloudWatch logs for general and audit logs if CloudWatch is enabled
logs {
general = var.general_log_enabled ? true : false
audit = var.audit_log_enabled ? true : false
}

maintenance_window_start_time {
day_of_week = var.maintenance_day_of_week
time_of_day = var.maintenance_time_of_day
time_zone = var.maintenance_time_zone
}

# Dynamically assign the user based on whether admin or application user exists
dynamic "user" {
for_each = length(var.mq_admin_user) > 0 || length(var.mq_application_user) > 0 ? [1] : []

content {
username = length(var.mq_admin_user) > 0 ? (
var.use_secrets_manager ? (
length(aws_secretsmanager_secret.mq_master_username_secret) > 0 ? jsondecode(aws_secretsmanager_secret_version.mq_master_username_version[0].secret_string).username : "default_admin_user"
) : (
length(data.aws_ssm_parameter.mq_master_username) > 0 ? data.aws_ssm_parameter.mq_master_username[0].value : "default_admin_user"
)
) : (
var.use_secrets_manager ? (
length(aws_secretsmanager_secret.mq_application_username_secret) > 0 ? jsondecode(aws_secretsmanager_secret_version.mq_application_username_version[0].secret_string).username : "default_application_user"
) : (
length(data.aws_ssm_parameter.mq_application_username) > 0 ? data.aws_ssm_parameter.mq_application_username[0].value : "default_application_user"
)
)

password = length(var.mq_admin_password) > 0 ? (
var.use_secrets_manager ? (
length(aws_secretsmanager_secret.mq_master_password_secret) > 0 ? jsondecode(aws_secretsmanager_secret_version.mq_master_password_version[0].secret_string).password : "Admin12345678!"
) : (
length(data.aws_ssm_parameter.mq_master_password) > 0 ? data.aws_ssm_parameter.mq_master_password[0].value : "Admin12345678!"
)
) : (
var.use_secrets_manager ? (
length(aws_secretsmanager_secret.mq_application_password_secret) > 0 ? jsondecode(aws_secretsmanager_secret_version.mq_application_password_version[0].secret_string).password : "App12345678!"
) : (
length(data.aws_ssm_parameter.mq_application_password) > 0 ? data.aws_ssm_parameter.mq_application_password[0].value : "App12345678!"
)
)

groups = var.mq_admin_groups
console_access = var.console_access
}
}

}

Check notice

Code scanning / defsec

MQ Broker should have general logging enabled Note

Broker does not have general logging enabled.
@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

Comment on lines 75 to 107
module "public_subnet" {
source = "clouddrove/subnet/aws"
version = "2.0.1"
name = "public-subnet"
environment = local.environment
label_order = local.label_order
availability_zones = ["us-west-1b", "us-west-1c"]
vpc_id = module.vpc.vpc_id
cidr_block = module.vpc.vpc_cidr_block
type = "public"
igw_id = module.vpc.igw_id
ipv6_cidr_block = module.vpc.ipv6_cidr_block
public_inbound_acl_rules = [
{
rule_number = 100
rule_action = "deny"
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_block = "10.0.1.0/24"
},
]
private_inbound_acl_rules = [
{
rule_number = 100
rule_action = "deny"
from_port = 0
to_port = 0
protocol = "-1"
cidr_block = "10.0.2.0/24"
},
]
}

Check failure

Code scanning / defsec

An ingress Network ACL rule allows ALL ports. Error

Network ACL rule allows access using ALL ports.
Comment on lines 111 to 156
module "mq_broker" {
source = "../.." # Reference the path of the root module where the MQ broker is defined

# Pass in the values to configure the MQ broker
aws_region = var.aws_region
mq_broker_name = var.mq_broker_name
engine_type = var.engine_type
engine_version = var.engine_version
host_instance_type = var.host_instance_type
broker_name = var.broker_name
deployment_mode = var.deployment_mode
maintenance_day_of_week = var.maintenance_day_of_week
maintenance_time = var.maintenance_time
tags = var.tags


# Pass in the VPC and Subnet created by the VPC and Subnet modules
vpc_id = module.vpc.vpc_id # Pass VPC ID
# subnet_ids = module.public_subnet.public_subnet_id
subnet_ids = [module.public_subnet.public_subnet_id[0]]
# Pass subnet IDs
security_group_id = [module.security_group.security_group_id]
# MQ broker-specific settings
apply_immediately = var.apply_immediately
auto_minor_version_upgrade = var.auto_minor_version_upgrade
publicly_accessible = var.publicly_accessible
general_log_enabled = var.general_log_enabled
audit_log_enabled = var.audit_log_enabled
kms_mq_key_arn = var.kms_mq_key_arn
use_aws_owned_key = var.use_aws_owned_key
ssm_path = var.ssm_path
encryption_enabled = var.encryption_enabled
kms_ssm_key_arn = var.kms_ssm_key_arn
allowed_ingress_ports = var.allowed_ingress_ports
additional_security_group_ids = var.additional_security_group_ids

# Admin and Application user credentials
mq_admin_user = var.mq_admin_user
mq_admin_password = var.mq_admin_password
mq_application_user = var.mq_application_username
mq_application_password = var.mq_application_password
alias = format(
"alias/%s",
replace(var.alias, "[^a-zA-Z0-9_-]", "_")
)
}

Check notice

Code scanning / defsec

CloudWatch log groups should be encrypted using CMK Note

Log group is not encrypted.
Comment on lines 111 to 156
module "mq_broker" {
source = "../.." # Reference the path of the root module where the MQ broker is defined

# Pass in the values to configure the MQ broker
aws_region = var.aws_region
mq_broker_name = var.mq_broker_name
engine_type = var.engine_type
engine_version = var.engine_version
host_instance_type = var.host_instance_type
broker_name = var.broker_name
deployment_mode = var.deployment_mode
maintenance_day_of_week = var.maintenance_day_of_week
maintenance_time = var.maintenance_time
tags = var.tags


# Pass in the VPC and Subnet created by the VPC and Subnet modules
vpc_id = module.vpc.vpc_id # Pass VPC ID
# subnet_ids = module.public_subnet.public_subnet_id
subnet_ids = [module.public_subnet.public_subnet_id[0]]
# Pass subnet IDs
security_group_id = [module.security_group.security_group_id]
# MQ broker-specific settings
apply_immediately = var.apply_immediately
auto_minor_version_upgrade = var.auto_minor_version_upgrade
publicly_accessible = var.publicly_accessible
general_log_enabled = var.general_log_enabled
audit_log_enabled = var.audit_log_enabled
kms_mq_key_arn = var.kms_mq_key_arn
use_aws_owned_key = var.use_aws_owned_key
ssm_path = var.ssm_path
encryption_enabled = var.encryption_enabled
kms_ssm_key_arn = var.kms_ssm_key_arn
allowed_ingress_ports = var.allowed_ingress_ports
additional_security_group_ids = var.additional_security_group_ids

# Admin and Application user credentials
mq_admin_user = var.mq_admin_user
mq_admin_password = var.mq_admin_password
mq_application_user = var.mq_application_username
mq_application_password = var.mq_application_password
alias = format(
"alias/%s",
replace(var.alias, "[^a-zA-Z0-9_-]", "_")
)
}

Check warning

Code scanning / defsec

MQ Broker should have audit logging enabled Warning

Broker does not have audit logging enabled.
Comment on lines 111 to 156
module "mq_broker" {
source = "../.." # Reference the path of the root module where the MQ broker is defined

# Pass in the values to configure the MQ broker
aws_region = var.aws_region
mq_broker_name = var.mq_broker_name
engine_type = var.engine_type
engine_version = var.engine_version
host_instance_type = var.host_instance_type
broker_name = var.broker_name
deployment_mode = var.deployment_mode
maintenance_day_of_week = var.maintenance_day_of_week
maintenance_time = var.maintenance_time
tags = var.tags


# Pass in the VPC and Subnet created by the VPC and Subnet modules
vpc_id = module.vpc.vpc_id # Pass VPC ID
# subnet_ids = module.public_subnet.public_subnet_id
subnet_ids = [module.public_subnet.public_subnet_id[0]]
# Pass subnet IDs
security_group_id = [module.security_group.security_group_id]
# MQ broker-specific settings
apply_immediately = var.apply_immediately
auto_minor_version_upgrade = var.auto_minor_version_upgrade
publicly_accessible = var.publicly_accessible
general_log_enabled = var.general_log_enabled
audit_log_enabled = var.audit_log_enabled
kms_mq_key_arn = var.kms_mq_key_arn
use_aws_owned_key = var.use_aws_owned_key
ssm_path = var.ssm_path
encryption_enabled = var.encryption_enabled
kms_ssm_key_arn = var.kms_ssm_key_arn
allowed_ingress_ports = var.allowed_ingress_ports
additional_security_group_ids = var.additional_security_group_ids

# Admin and Application user credentials
mq_admin_user = var.mq_admin_user
mq_admin_password = var.mq_admin_password
mq_application_user = var.mq_application_username
mq_application_password = var.mq_application_password
alias = format(
"alias/%s",
replace(var.alias, "[^a-zA-Z0-9_-]", "_")
)
}

Check notice

Code scanning / defsec

MQ Broker should have general logging enabled Note

Broker does not have general logging enabled.
Comment on lines 111 to 156
module "mq_broker" {
source = "../.." # Reference the path of the root module where the MQ broker is defined

# Pass in the values to configure the MQ broker
aws_region = var.aws_region
mq_broker_name = var.mq_broker_name
engine_type = var.engine_type
engine_version = var.engine_version
host_instance_type = var.host_instance_type
broker_name = var.broker_name
deployment_mode = var.deployment_mode
maintenance_day_of_week = var.maintenance_day_of_week
maintenance_time = var.maintenance_time
tags = var.tags


# Pass in the VPC and Subnet created by the VPC and Subnet modules
vpc_id = module.vpc.vpc_id # Pass VPC ID
# subnet_ids = module.public_subnet.public_subnet_id
subnet_ids = [module.public_subnet.public_subnet_id[0]]
# Pass subnet IDs
security_group_id = [module.security_group.security_group_id]
# MQ broker-specific settings
apply_immediately = var.apply_immediately
auto_minor_version_upgrade = var.auto_minor_version_upgrade
publicly_accessible = var.publicly_accessible
general_log_enabled = var.general_log_enabled
audit_log_enabled = var.audit_log_enabled
kms_mq_key_arn = var.kms_mq_key_arn
use_aws_owned_key = var.use_aws_owned_key
ssm_path = var.ssm_path
encryption_enabled = var.encryption_enabled
kms_ssm_key_arn = var.kms_ssm_key_arn
allowed_ingress_ports = var.allowed_ingress_ports
additional_security_group_ids = var.additional_security_group_ids

# Admin and Application user credentials
mq_admin_user = var.mq_admin_user
mq_admin_password = var.mq_admin_password
mq_application_user = var.mq_application_username
mq_application_password = var.mq_application_password
alias = format(
"alias/%s",
replace(var.alias, "[^a-zA-Z0-9_-]", "_")
)
}

Check notice

Code scanning / defsec

Secrets Manager should use customer managed keys Note

Secret explicitly uses the default key.
Comment on lines 111 to 156
module "mq_broker" {
source = "../.." # Reference the path of the root module where the MQ broker is defined

# Pass in the values to configure the MQ broker
aws_region = var.aws_region
mq_broker_name = var.mq_broker_name
engine_type = var.engine_type
engine_version = var.engine_version
host_instance_type = var.host_instance_type
broker_name = var.broker_name
deployment_mode = var.deployment_mode
maintenance_day_of_week = var.maintenance_day_of_week
maintenance_time = var.maintenance_time
tags = var.tags


# Pass in the VPC and Subnet created by the VPC and Subnet modules
vpc_id = module.vpc.vpc_id # Pass VPC ID
# subnet_ids = module.public_subnet.public_subnet_id
subnet_ids = [module.public_subnet.public_subnet_id[0]]
# Pass subnet IDs
security_group_id = [module.security_group.security_group_id]
# MQ broker-specific settings
apply_immediately = var.apply_immediately
auto_minor_version_upgrade = var.auto_minor_version_upgrade
publicly_accessible = var.publicly_accessible
general_log_enabled = var.general_log_enabled
audit_log_enabled = var.audit_log_enabled
kms_mq_key_arn = var.kms_mq_key_arn
use_aws_owned_key = var.use_aws_owned_key
ssm_path = var.ssm_path
encryption_enabled = var.encryption_enabled
kms_ssm_key_arn = var.kms_ssm_key_arn
allowed_ingress_ports = var.allowed_ingress_ports
additional_security_group_ids = var.additional_security_group_ids

# Admin and Application user credentials
mq_admin_user = var.mq_admin_user
mq_admin_password = var.mq_admin_password
mq_application_user = var.mq_application_username
mq_application_password = var.mq_application_password
alias = format(
"alias/%s",
replace(var.alias, "[^a-zA-Z0-9_-]", "_")
)
}

Check notice

Code scanning / defsec

Secrets Manager should use customer managed keys Note

Secret explicitly uses the default key.
Comment on lines 111 to 156
module "mq_broker" {
source = "../.." # Reference the path of the root module where the MQ broker is defined

# Pass in the values to configure the MQ broker
aws_region = var.aws_region
mq_broker_name = var.mq_broker_name
engine_type = var.engine_type
engine_version = var.engine_version
host_instance_type = var.host_instance_type
broker_name = var.broker_name
deployment_mode = var.deployment_mode
maintenance_day_of_week = var.maintenance_day_of_week
maintenance_time = var.maintenance_time
tags = var.tags


# Pass in the VPC and Subnet created by the VPC and Subnet modules
vpc_id = module.vpc.vpc_id # Pass VPC ID
# subnet_ids = module.public_subnet.public_subnet_id
subnet_ids = [module.public_subnet.public_subnet_id[0]]
# Pass subnet IDs
security_group_id = [module.security_group.security_group_id]
# MQ broker-specific settings
apply_immediately = var.apply_immediately
auto_minor_version_upgrade = var.auto_minor_version_upgrade
publicly_accessible = var.publicly_accessible
general_log_enabled = var.general_log_enabled
audit_log_enabled = var.audit_log_enabled
kms_mq_key_arn = var.kms_mq_key_arn
use_aws_owned_key = var.use_aws_owned_key
ssm_path = var.ssm_path
encryption_enabled = var.encryption_enabled
kms_ssm_key_arn = var.kms_ssm_key_arn
allowed_ingress_ports = var.allowed_ingress_ports
additional_security_group_ids = var.additional_security_group_ids

# Admin and Application user credentials
mq_admin_user = var.mq_admin_user
mq_admin_password = var.mq_admin_password
mq_application_user = var.mq_application_username
mq_application_password = var.mq_application_password
alias = format(
"alias/%s",
replace(var.alias, "[^a-zA-Z0-9_-]", "_")
)
}

Check notice

Code scanning / defsec

Secrets Manager should use customer managed keys Note

Secret explicitly uses the default key.
Comment on lines 111 to 156
module "mq_broker" {
source = "../.." # Reference the path of the root module where the MQ broker is defined

# Pass in the values to configure the MQ broker
aws_region = var.aws_region
mq_broker_name = var.mq_broker_name
engine_type = var.engine_type
engine_version = var.engine_version
host_instance_type = var.host_instance_type
broker_name = var.broker_name
deployment_mode = var.deployment_mode
maintenance_day_of_week = var.maintenance_day_of_week
maintenance_time = var.maintenance_time
tags = var.tags


# Pass in the VPC and Subnet created by the VPC and Subnet modules
vpc_id = module.vpc.vpc_id # Pass VPC ID
# subnet_ids = module.public_subnet.public_subnet_id
subnet_ids = [module.public_subnet.public_subnet_id[0]]
# Pass subnet IDs
security_group_id = [module.security_group.security_group_id]
# MQ broker-specific settings
apply_immediately = var.apply_immediately
auto_minor_version_upgrade = var.auto_minor_version_upgrade
publicly_accessible = var.publicly_accessible
general_log_enabled = var.general_log_enabled
audit_log_enabled = var.audit_log_enabled
kms_mq_key_arn = var.kms_mq_key_arn
use_aws_owned_key = var.use_aws_owned_key
ssm_path = var.ssm_path
encryption_enabled = var.encryption_enabled
kms_ssm_key_arn = var.kms_ssm_key_arn
allowed_ingress_ports = var.allowed_ingress_ports
additional_security_group_ids = var.additional_security_group_ids

# Admin and Application user credentials
mq_admin_user = var.mq_admin_user
mq_admin_password = var.mq_admin_password
mq_application_user = var.mq_application_username
mq_application_password = var.mq_application_password
alias = format(
"alias/%s",
replace(var.alias, "[^a-zA-Z0-9_-]", "_")
)
}

Check notice

Code scanning / defsec

Secrets Manager should use customer managed keys Note

Secret explicitly uses the default key.
@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

…and depends on in main module to ensure resources created in right order
@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@clouddrove-ci
Copy link
Member

Terraform Security Scan Failed

Show Output

@VishwajitNagulkar VishwajitNagulkar merged commit 9c9a357 into master Nov 15, 2024
2 of 3 checks passed
@VishwajitNagulkar VishwajitNagulkar deleted the feat/amazon-mq branch November 19, 2024 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants