Giter Club home page Giter Club logo

terraform-provider-sdm's Introduction

Terraform Provider for StrongDM

You can use the StrongDM Terraform provider to configure and manage your StrongDM account and resources. This project allows you to leverage Terraform to complete the following tasks in StrongDM:

  • Create and register gateways or relays
  • Enroll databases, servers, clusters, and websites
  • Create, manage, and suspend users
  • Grant user and resource access
  • Manage roles
  • Manage access workflows

For more detailed examples using the StrongDM provider and Amazon Web Services (AWS) or Microsoft Azure, check the following resources:

Requirements

Versioning

StrongDM uses semantic versioning. We do not guarantee compatibility between major versions. Be sure to use version constraints to pin your dependency to the desired major version of the StrongDM Terraform provider.

Authentication

If you do not already have them, you must generate a set of API keys.

Environment Variables

You can provide your credentials via the SDM_API_ACCESS_KEY and SDM_API_SECRET_KEY environment variables.

$ export SDM_API_ACCESS_KEY="<ACCESS_KEY>"
$ export SDM_API_SECRET_KEY="<SECRET_KEY>"
$ terraform plan

Provider statement

provider "sdm" {}

Direct

If it is not possible to use environment variables, add the API keys directly to the provider statement as follows:

provider "sdm" {
    api_access_key = "<ACCESS_KEY>"
    api_secret_key = "<SECRET_KEY>"
}

Basic Example

Use the following basic example to create a gateway in StrongDM with the Terraform provider.

resource "sdm_node" "example_gateway" {
    gateway {
        name = "example gateway"
        listen_address = "localhost:5000"
        bind_address = "0.0.0.0:5000"
    }
}
$ terraform plan
$ terraform apply

Useful Links

Contributions

Currently, we are not accepting pull requests directly to this repository, but our users are some of the most resourceful and ambitious folks out there. If you have something to contribute, find a bug, or just want to give us some feedback, please email [email protected].

Running Integration Tests

Important: These are integration tests. They will create and destroy real resources in your account!

  1. First, clone this repository.

  2. In order to run the tests you must set these environment variables so that the provider can authenticate:

$ export SDM_API_ACCESS_KEY="<ACCESS_KEY>"
$ export SDM_API_SECRET_KEY="<SECRET_KEY>"
  1. From the cloned repo, run:
$ cd terraform-provider-sdm
$ TF_ACC=yes go test ./sdm -v -count=1 -mod=vendor

You must set TF_ACC=yes in order to run tests. IF TF_ACC=yes is not set, all tests will pass without any action.

License

Mozilla Public License 2.0

terraform-provider-sdm's People

Contributors

200sc avatar britt avatar calebmchenry avatar curiosity26 avatar dbinger avatar etodd avatar kjamieson-sdm avatar kungfukennyg avatar philhassey avatar supportsdm avatar thefellow avatar ucirello avatar wcraigjones avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

terraform-provider-sdm's Issues

add way to set default tags

We have a lot of terrraform modules that create SDM Resources for their service that they are creating and while copying and pasting the tags around easy enough, it could cause some drift if something is missed.

What I'm looking for is to have the sdm provider work like how the aws provider does where you can define default tags, so it would look something like this:

provider "aws" {
  region  = var.aws_region
  profile = "my-aws-profile"

  default_tags {
    tags = module.tags.tags_no_name
  }
}

provider "sdm" {
  default_tags {
    tags = module.tags.tags_no_name
  }
}

That ways all created resources will have the same set of tags that we can then create dynamic roles for.

Terraform does not catch username and password changes done on the website

Hi,

Once a sdm_resource is created, if the username or the password is changed on strongdm.com, terraform does not know about it.

Here's a reproducible example:

terraform {
  required_providers {
    sdm = {
      source  = "strongdm/sdm"
    }
  }
}


resource "sdm_resource" "test" {
    postgres {
        name = "postgres-test"
        hostname = "example.com"
        database = "my-db"
        username = "admin"
        password = "hunter2"
        port = 5432
        tags = {
            region = "us-west"
            env = "dev"
        }
    }
}
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Now if I terraform plan, all good:

No changes. Your infrastructure matches the configuration.

The problem is if I change the username or the password on the website:
Capture d’écran 2023-03-29 à 18 01 41
If I plan, I still get no changes:

No changes. Your infrastructure matches the configuration.

While I should see terraform stating that a sensible value has changed.

This works if I change some other properties, like the hostname:

Terraform will perform the following actions:

  # sdm_resource.test will be updated in-place
  ~ resource "sdm_resource" "test" {
        id = "rs-35b6cbbd64245ffb"

      ~ postgres {
          ~ hostname          = "example.com2" -> "example.com"
            name              = "postgres-test"
            tags              = {
                "env"    = "dev"
                "region" = "us-west"
            }
            # (8 unchanged attributes hidden)
        }
    }

Plan: 0 to add, 1 to change, 0 to destroy.

This is problematic because we use terraform to make sure the passwords on all our systems match, and this behavior means we can never be sure that what's in strongdm is the password we set initially. If someone in our team fixed a password in strongdm and in the database, we'll never know in terraform, and on the next apply we might overwrite the fixed password without knowing.

Provider "sdm" not available for installation

The result of terraform init was:

Initializing the backend...

Initializing provider plugins...
- Checking for available provider plugins...

Provider "sdm" not available for installation.

A provider named "sdm" could not be found in the Terraform Registry.

This may result from mistyping the provider name, or the given provider may
be a third-party provider that cannot be installed automatically.

In the latter case, the plugin must be installed manually by locating and
downloading a suitable distribution package and placing the plugin's executable
file in the following directory:
    terraform.d/plugins/darwin_amd64

Terraform detects necessary plugins by inspecting the configuration and state.
To view the provider versions requested by each module, run
"terraform providers".


Error: no provider exists with the given name

It appears that doing a go build of this repo and placing it in ~/.terraform.d/plugins/darwin_amd64 (because I'm on a mac) solves this error.
My request is two parts:

  • Could this manual correction be documented please?
  • Could this be added to the official Terraform providers so that it gets installed automatically?

Changing the `sdm_resource` type doesn't cause a replacement

To repro:

apply the below:

resource "sdm_resource" "teamcity_database" {
  azure_postgres {
    database = "example"
    hostname = azurerm_mysql_flexible_server.example.fqdn
    name     = "example"

    username = local.readonly_database_username
    password = random_password.readonly_user_password.result
  }
}

Then, realise your error, and update your terraform config to:

resource "sdm_resource" "teamcity_database" {
  azure_mysql {
    database = "example"
    hostname = azurerm_mysql_flexible_server.example.fqdn
    name     = "example"

    username = local.readonly_database_username
    password = random_password.readonly_user_password.result
  }
}

Expected: The provider handles the change by removing the incorrect datasource and adding the right one.

Actual:
Plan shows an update-in-place for the resource, but then apply says:

Error: cannot update Resource rs-75a3e27b64e2fa2f: invalid operation: type does not match original resource (rs-75a3e27b64e2fa2f)

1.0.8 and 1.0.9 fail to install, 1.0.7 works

The following works:

provider sdm {
  version = "1.0.7"
}

But the following fails:

provider sdm {
  version = "1.0.8"
}

With the following error:

Initializing the backend...
2020/08/25 13:12:08 [TRACE] Preserving existing state lineage "05c5744c-9ee7-c542-3c3e-3a76e2dc7ccc"
2020/08/25 13:12:08 [TRACE] Preserving existing state lineage "05c5744c-9ee7-c542-3c3e-3a76e2dc7ccc"
2020/08/25 13:12:08 [TRACE] Meta.Backend: working directory was previously initialized for "remote" backend
2020/08/25 13:12:08 [TRACE] Meta.Backend: using already-initialized, unchanged "remote" backend configuration
2020/08/25 13:12:08 [DEBUG] Service discovery for <<redacted>> at https://<<redacted>>/.well-known/terraform.json
2020/08/25 13:12:08 [TRACE] HTTP client GET request to https://<<redacted>>/.well-known/terraform.json
2020/08/25 13:12:09 [DEBUG] Retrieve version constraints for service tfe.v2.1 and product terraform
2020/08/25 13:12:09 [TRACE] HTTP client GET request to https://checkpoint-api.hashicorp.com/v1/versions/tfe.v2.1?product=terraform
2020/08/25 13:12:10 [TRACE] Meta.Backend: instantiated backend of type *remote.Remote
2020/08/25 13:12:10 [DEBUG] checking for provider in "."
2020/08/25 13:12:10 [DEBUG] checking for provider in "/usr/local/Cellar/tfenv/2.0.0/versions/0.12.26"
2020/08/25 13:12:10 [DEBUG] checking for provider in ".terraform/plugins/darwin_amd64"
2020/08/25 13:12:10 [DEBUG] found provider "terraform-provider-aws_v2.68.0_x4"
2020/08/25 13:12:10 [DEBUG] found provider "terraform-provider-null_v2.1.2_x4"
2020/08/25 13:12:10 [DEBUG] found provider "terraform-provider-sdm_v1.0.7"
2020/08/25 13:12:10 [DEBUG] found provider "terraform-provider-template_v2.1.2_x4"
2020/08/25 13:12:10 [DEBUG] found valid plugin: "aws", "2.68.0", "/Users/<<redacted>>/workspaces/<<redacted>>/.terraform/plugins/darwin_amd64/terraform-provider-aws_v2.68.0_x4"
2020/08/25 13:12:10 [DEBUG] found valid plugin: "null", "2.1.2", "/Users/<<redacted>>/workspaces/<<redacted>>/.terraform/plugins/darwin_amd64/terraform-provider-null_v2.1.2_x4"
2020/08/25 13:12:10 [DEBUG] found valid plugin: "sdm", "1.0.7", "/Users/<<redacted>>/workspaces/<<redacted>>/.terraform/plugins/darwin_amd64/terraform-provider-sdm_v1.0.7"
2020/08/25 13:12:10 [DEBUG] found valid plugin: "template", "2.1.2", "/Users/<<redacted>>/workspaces/<<redacted>>/.terraform/plugins/darwin_amd64/terraform-provider-template_v2.1.2_x4"
2020/08/25 13:12:10 [DEBUG] checking for provisioner in "."
2020/08/25 13:12:10 [DEBUG] checking for provisioner in "/usr/local/Cellar/tfenv/2.0.0/versions/0.12.26"
2020/08/25 13:12:10 [DEBUG] checking for provisioner in ".terraform/plugins/darwin_amd64"
2020/08/25 13:12:10 [TRACE] Meta.Backend: backend *remote.Remote supports operations
2020/08/25 13:12:11 [DEBUG] checking for provider in "."
2020/08/25 13:12:11 [DEBUG] checking for provider in "/usr/local/Cellar/tfenv/2.0.0/versions/0.12.26"
2020/08/25 13:12:11 [DEBUG] checking for provider in ".terraform/plugins/darwin_amd64"
2020/08/25 13:12:11 [DEBUG] found provider "terraform-provider-aws_v2.68.0_x4"
2020/08/25 13:12:11 [DEBUG] found provider "terraform-provider-null_v2.1.2_x4"
2020/08/25 13:12:11 [DEBUG] found provider "terraform-provider-sdm_v1.0.7"
2020/08/25 13:12:11 [DEBUG] found provider "terraform-provider-template_v2.1.2_x4"
2020/08/25 13:12:11 [DEBUG] found valid plugin: "null", "2.1.2", "/Users/<<redacted>>/workspaces/<<redacted>>/.terraform/plugins/darwin_amd64/terraform-provider-null_v2.1.2_x4"
2020/08/25 13:12:11 [DEBUG] found valid plugin: "sdm", "1.0.7", "/Users/<<redacted>>/workspaces/<<redacted>>/.terraform/plugins/darwin_amd64/terraform-provider-sdm_v1.0.7"
2020/08/25 13:12:11 [DEBUG] found valid plugin: "template", "2.1.2", "/Users/<<redacted>>/workspaces/<<redacted>>/.terraform/plugins/darwin_amd64/terraform-provider-template_v2.1.2_x4"
2020/08/25 13:12:11 [DEBUG] found valid plugin: "aws", "2.68.0", "/Users/<<redacted>>/workspaces/<<redacted>>.terraform/plugins/darwin_amd64/terraform-provider-aws_v2.68.0_x4"

2020/08/25 13:12:11 [DEBUG] plugin requirements: "aws"="~> 2.0,~> 2.0"
2020/08/25 13:12:11 [DEBUG] plugin requirements: "sdm"="1.0.8"
2020/08/25 13:12:11 [DEBUG] plugin requirements: "null"=""
2020/08/25 13:12:11 [DEBUG] plugin requirements: "template"=""
2020/08/25 13:12:11 [DEBUG] Service discovery for registry.terraform.io at https://registry.terraform.io/.well-known/terraform.json
2020/08/25 13:12:11 [TRACE] HTTP client GET request to https://registry.terraform.io/.well-known/terraform.json
Initializing provider plugins...
- Checking for available provider plugins...
2020/08/25 13:12:11 [DEBUG] fetching provider versions from "https://registry.terraform.io/v1/providers/-/sdm/versions"
2020/08/25 13:12:11 [DEBUG] GET https://registry.terraform.io/v1/providers/-/sdm/versions
2020/08/25 13:12:11 [TRACE] HTTP client GET request to https://registry.terraform.io/v1/providers/-/sdm/versions
2020/08/25 13:12:11 [DEBUG] fetching provider location from "https://registry.terraform.io/v1/providers/terraform-providers/sdm/1.0.8/download/darwin/amd64"
2020/08/25 13:12:11 [DEBUG] GET https://registry.terraform.io/v1/providers/terraform-providers/sdm/1.0.8/download/darwin/amd64
2020/08/25 13:12:11 [TRACE] HTTP client GET request to https://registry.terraform.io/v1/providers/terraform-providers/sdm/1.0.8/download/darwin/amd64
2020/08/25 13:12:11 [TRACE] HTTP client GET request to https://releases.hashicorp.com/terraform-provider-sdm/1.0.8/terraform-provider-sdm_1.0.8_SHA256SUMS
2020/08/25 13:12:11 [TRACE] HTTP client GET request to https://releases.hashicorp.com/terraform-provider-sdm/1.0.8/terraform-provider-sdm_1.0.8_SHA256SUMS.sig
2020/08/25 13:12:11 [DEBUG] verified GPG signature with key from HashiCorp Security <[email protected]>
2020/08/25 13:12:11 [DEBUG] getting provider "sdm" (terraform-providers/sdm) version "1.0.8"
2020/08/25 13:12:11 [DEBUG] plugin cache is disabled, so downloading sdm 1.0.8 from https://releases.hashicorp.com/terraform-provider-sdm/1.0.8/terraform-provider-sdm_1.0.8_darwin_amd64.zip?checksum=sha256:5454f95211ec0baa4ed43a532b743d390e4a71974915722951ceb19878adf77a
- Downloading plugin for provider "sdm" (terraform-providers/sdm) 1.0.8...
2020/08/25 13:12:11 [TRACE] HTTP client HEAD request to https://releases.hashicorp.com/terraform-provider-sdm/1.0.8/terraform-provider-sdm_1.0.8_darwin_amd64.zip
2020/08/25 13:12:11 [TRACE] HTTP client GET request to https://releases.hashicorp.com/terraform-provider-sdm/1.0.8/terraform-provider-sdm_1.0.8_darwin_amd64.zip
2020/08/25 13:12:12 [DEBUG] looking for the sdm 1.0.8 plugin we just installed
2020/08/25 13:12:12 [DEBUG] checking for provider in ".terraform/plugins/darwin_amd64"
2020/08/25 13:12:12 [DEBUG] found provider "terraform-provider-aws_v2.68.0_x4"
2020/08/25 13:12:12 [DEBUG] found provider "terraform-provider-null_v2.1.2_x4"
2020/08/25 13:12:12 [WARN] found legacy provider "terraform-provider-sdm_1.0.8"
2020/08/25 13:12:12 [DEBUG] found provider "terraform-provider-sdm_v1.0.7"
2020/08/25 13:12:12 [DEBUG] found provider "terraform-provider-template_v2.1.2_x4"
2020/08/25 13:12:12 [DEBUG] all plugins found discovery.PluginMetaSet{discovery.PluginMeta{Name:"aws", Version:"2.68.0", Path:"/Users/<<redacted>>/workspaces/<<redacted>>/.terraform/plugins/darwin_amd64/terraform-provider-aws_v2.68.0_x4"}:
struct {}{}, discovery.PluginMeta{Name:"null", Version:"2.1.2", Path:"/Users/<<redacted>>/workspaces/<<redacted>>/.terraform/plugins/darwin_amd64/terraform-provider-null_v2.1.2_x4"}:struct {}{}, discovery.PluginMeta{Name:"sdm", Version:"1.
0.7", Path:"/Users/<<redacted>>/workspaces/<<redacted>>/.terraform/plugins/darwin_amd64/terraform-provider-sdm_v1.0.7"}:struct {}{}, discovery.PluginMeta{Name:"sdm_1.0.8", Version:"0.0.0", Path:"/Users/<<redacted>>/workspaces/<<redacted>>/.terraform/plugins/darwin_amd64/terraform-provider-sdm_1.0.8"}:struct {}{}, discovery.PluginMeta{Name:"template", Version:"2.1.2", Path:"/Users/<<redacted>>/workspaces/<<redacted>>/.terraform/plugins/darwin_amd64/terraform-provider-template_v2.1.2_x4"}:struct {}{}}
2020/08/25 13:12:12 [DEBUG] filtered plugins discovery.PluginMetaSet{}

Error installing provider "sdm": failed to find installed plugin version 1.0.8; this is a bug in Terraform and should be reported.

Terraform analyses the configuration and state and automatically downloads
plugins for the providers used. However, when attempting to download this
plugin an unexpected error occurred.

This may be caused if for some reason Terraform is unable to reach the
plugin repository. The repository may be unreachable if access is blocked
by a firewall.

If automatic installation is not possible or desirable in your environment,
you may alternatively manually install plugins by downloading a suitable
distribution package and placing the plugin's executable file in the
following directory:
    terraform.d/plugins/darwin_amd64


Error: failed to find installed plugin version 1.0.8; this is a bug in Terraform and should be reported

This is using Terraform 0.12.26. The install of 1.0.7 doesn't seem to trigger the found legacy provider warning. I wonder if that is related. It is possible this is a Terraform problem like the error says, but given version 1.0.7 installs fine, I'm guessing it was something to do with the publishing of 1.0.8.

secret_store_id change should force new resource

Currently, updating the secret_store_id shows the resource will be updated instead of replaced. Terraform apply fails with the following error:

│ Error: cannot update Resource rs-2643b042646bff49: failed to update resource rs-2643b042646bff49: invalid operation: secret store does not match original resource (rs-2643b042646bff49)

This operation should flag the resource to be destroyed and re-created.

sdm_account cannot apply new tags to users

Trying to add some simple tags to existing user accounts in TF errors out with a permission error, even for admin users. Adding the same tags via the SDM CLI works just fine. I've also validated that my API key used by the provider has all 8 user permissions.


Example configuration:

resource "sdm_account" "user" {
  user {
    first_name = "First"
    last_name  = "Last"
    email      = [email protected]

    tags = {
      "country"    = "CANADA
    }
  }

Example error:

│ Error: cannot update Account a-xxxxxxxx: permission denied: access denied
│ 
│   with sdm_account.user,
│   on dev-team.tf line 15, in resource "sdm_account" "user":
│  15: resource "sdm_account" "user" {
│ 

Example CLI command that works with my permissions:

sdm admin users update --email [email protected] --tags 'country=US'

cannot read SecretStore: unauthenticated: cannot find auth GUID

This was working before but now I get this error when trying to run terraform plan.

I have a vault app role for the secret store. I have the env vars for the sdm api key.

What can cause these errors?

Error: cannot read SecretStore se-<redacted>: unauthenticated: cannot find auth GUID
│
│   with module.my_relay.sdm_secret_store.vault_app_role_integration,
│   on modules/my_gateway/main.tf line 1, in resource "sdm_secret_store" "vault_app_role_integration":
│    1: resource "sdm_secret_store" "vault_app_role_integration" {
│
╵

╷
│ Error: cannot read Node n-6b5c21f8627ggz86: unauthenticated: cannot find auth GUID
│
│   with module.gateway.sdm_node.gateway[0],
│   on modules/my_gateway/main.tf line 47, in resource "sdm_node" "gateway":
│   47: resource "sdm_node" "gateway" {
│

Missing Import Examples

Most Terraform providers provide an example command to import existing infrastructure into their code. If would be nice to have those commands readily available in the Terraform providers documentation, to avoid the need to dig in order to find out how to import a resource

Add support for encrypted aws_iam_access_key

It would be nice to be able to use aws_iam_access_key with an sdm_resource without the secret key ending up unencrypted in the state file. The aws_iam_access_key resource supports a pgp_key argument which can be used to encrypt the generated secret key. It would be nice if this could be used to prevent the secret key needing to end up in the state file. I understand that this likely will require changes beyond the terraform provider, but it would help a lot in being able to keep exposure to a minimum.

Would something like this be possible?

Docs seem to duplicate content/unclear as to which docs are correct

Hi StrongDM team,

I've been reviewing the docs and noticed that there are two sub directories which seem to duplicate content:

  • Resources
  • Data Sources

Additionally, given the content seems duplicated, it's unclear to me as to which set of docs are the canonical set of docs to follow for the provider, the "Resources" or "Data Sources" docs. FYI I had started down the path of attempting to fix the broken "Resources" link from the main pages site (looks like there's a index.md file missing in the "Resources" directory), which is what sent me down this rabbit hole 🙃

v1.0.21+ fails to compile compile, complains about sdm.SSHCustomerKey

# github.com/strongdm/terraform-provider-sdm/sdm
--
275 | pkg/mod/github.com/strongdm/[email protected]/sdm/data_source_resource.go:3932:9: undefined: sdm.SSHCustomerKey
276 | pkg/mod/github.com/strongdm/[email protected]/sdm/resource_resource.go:6937:12: undefined: sdm.SSHCustomerKey
277 | pkg/mod/github.com/strongdm/[email protected]/sdm/resource_resource.go:6939:11: undefined: sdm.SSHCustomerKey
278 | pkg/mod/github.com/strongdm/[email protected]/sdm/resource_resource.go:7987:8: undefined: sdm.SSHCustomerKey
279 | pkg/mod/github.com/strongdm/[email protected]/sdm/resource_resource.go:9151:8: undefined: sdm.SSHCustomerKey

Datasource with secret store change fails to recreate the datasource

When a secret store id changes for a datasource, the datasource can't update itself, and it doesn't know to do a destroy/create operation, so it fails to update the secret store id.

 # sdm_resource.db will be updated in-place
  ~ resource "sdm_resource" "db" {
        id = "rs-089b966f60b17305"

      ~ aurora_mysql {
          ~ secret_store_id            = "se-67a9204a60b111e5" -> "se-2925693860c7e1f4"
        }
    }

Error: cannot update Resource rs-089b966f60b17305: failed to update resource rs-089b966f60b17305: invalid operation: secret store does not match original resource (rs-089b966f60b17305)

resource exhausted: Sorry! You've made too many requests, try again

Hi,

We have a big users base in strongdm and need to regularly plan it (users, grants, resources) to make sure it's not out of date.

We are now hitting the API limit each time we want to plan. Support granted us 2x the limit so we can now plan again, but this is going to be problematic again as we ramp up more resources and users.

Support suggested us to use https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep to time the requests, but as the doc states, it's supposed to be a workaround until the provider handles the rate limiting itself, and times retries based on the API telling it how to time its requets.

Can we get timed requests at the provider level to prevent plan/apply to fail on big setups?

username is not imported for mongo db resources

I believe I have discovered a bug with the SDM Terraform provider. I am importing MongoDB replica set resources into Terraform (v0.13.7) as sdm_resource with mongo_legacy_replicaset blocks.

Most of the fields from my SDM resource are imported correctly, but it seems like username is not. Using the Python SDM client I've verified that the resources I'm importing do indeed have a username set, but these are not reflected in the Terraform plan after importing them.

Wanted to get some clarification on whether this is a known issue, potential workarounds, and whether a fix is planned. Thanks!

Cluster resource certificate_authority not populated in SDM

When creating any variety of Kubernetes cluster, the value supplied for certificate_authority does not actually persist into SDM, leading to a cluster configuration that doesn't work.

Missing platform: `darwin_arm64`

When trying to install the provider on darwin_arm64 (Apple M1 Pro) I get:

╷
│ Error: Incompatible provider version
│ 
│ Provider registry.terraform.io/strongdm/sdm v1.0.31 does not have a package available for your current platform, darwin_arm64.
│ 
│ Provider releases are separate from Terraform CLI releases, so not all providers are available for all platforms. Other versions of this provider may have different platforms supported.
╵

Support for mapping sdm_roles with sdm_datasource using "name" as identifier instead of relying on tags or id

[FEATURE REQUEST]

  • Support for mapping sdm_roles with sdm_resource using "name" as identifier instead of relying on tags or id.

Additional Information:

Terraform v1.0.6
on darwin_amd64

  • provider registry.terraform.io/strongdm/sdm v2.6.0

We are leveraging access_rules from sdm_roles to map resources. The challenge is,

  1. We don't proper tags on resources, and ids are not that human understandable to manage and improve role assignment
  2. Don't want to rely on just type of datasource,
  3. Relying on just tags to assign datasource to roles has lot of problems like, to many tags to control for product/cross-product team, environment, level of access.
  4. assigning few datasources to multiple roles
  5. we need something kind of one to one mapping wherein we pass a list of Datasource NAME to sdm role access rules for resource mapping.

Split sdm_role resource and use attachments

When using an external provider such as Okta to manage roles and members you can't readily manage the access for those roles with Terraform.

It'd be better to split this resource up so that the policy is separate from the role. In fact, it'd be nice if even in StrongDM itself Policy could be separate and perhaps attached to multiple roles, similar to the way AWS IAM Roles/Policy works. But even without that, it'd be nice to have something like:

data "sdm_role" "some_role" {}

resource "sdm_role_policy_attachment" "some_policy" {
  role = data.sdm_role.some_role.id
  policy = jsonencode([{...}])
}

Error: "ssh.0.public_key": this field cannot be set

Ran into this error

Error: "ssh.0.public_key": this field cannot be set

when trying to create multiple servers with the same ssh public_key

TF snippet like this

resource "sdm_resource" "ssh_test_user" {
  ssh {
    name     = "node1"
    hostname = "192.168.111.111"
    username = "testuser"
    port     = 22
  }
}

resource "sdm_resource" "ssh_test_user_more" {
  ssh {
    name     = "node2"
    hostname = "192.168.111.112"
    username = sdm_resource.ssh_test_user.ssh[0].username
    port     = 22
    public_key = sdm_resource.ssh_test_user.ssh[0].public_key
  }
  ssh {
    name     = "node3"
    hostname = "192.168.111.113"
    username = sdm_resource.ssh_test_user.ssh[0].username
    port     = 22
    public_key = sdm_resource.ssh_test_user.ssh[0].public_key
  }
}

It works if we comment out the public_key but then they end up with different ssh_keys

Is it possible to create the resources with the same public key like the sdm admin ssh clone command?

SDM Gateway Token as Output to Terraform Gateway Module

Following from this implementation https://registry.terraform.io/providers/strongdm/sdm/latest/docs/guides/how_to_create_a_gateway.

I have a terraform module that bootstrap a virtual machine as strongDM gateway on google cloud. I am trying to automate the entire process with terraform by following the above link to output the token as input to Gateway module. This is generating a strange error that is very difficult to interpret. Now I don't know if I am doing something wrong with this simple code.

main.tf

resource "sdm_node" "gateway_1" {
  gateway {
    name           = "${var.gateway_number}-1"
    listen_address = "1.1.1.1:${var.gateway_port}"
  }
}

output.tf

output "gateway_1_token" {
  value = "${sdm_node.gateway_1[0].token}"
  sensitive = true
}

Here is the error from terraform plan

Error: Error loading modules: module strongdm_gateways: Error loading .terraform/modules/6437dd99385fd35cdf8bdb458b9f5139/output.tf: Error reading config for output gateway_1_token: parse error at 1:33: expected "}" but found "."

I expect that the token keyword should be making appropriate API call to strongDM to generate the token as it is not explicitly defined at the resource level in main.tf

The error message seems explanatory but appears totally unrelated to what I am trying to do here. Can some please help with interpretation of this error?

Example in Data Source documentation for `sdm_resource` is incorrect

The Data Source documentation for sdm_resource from https://registry.terraform.io/providers/strongdm/sdm/latest/docs/data-sources/resource#example-usage lists this as example usage:

data "sdm_resource" "mysql_datasources" {
    name = "us-west*"
    type = "mysql"
    tags = {
        region = "us-west"
        env = "dev"
    }    
}

Running this against a strongDM organization formatted as the above with the latest version of the provider produces this error:

% terraform plan
╷
│ Error: Unsupported argument
│
│   on main.tf line 14, in data "sdm_resource" "datasources":
│   14:     tags = {
│
│ An argument named "tags" is not expected here.

This isn't documented as a valid Argument on the same page, so I think this is just a case of removing the tags line from the example.

Passwords, secrets, keys and other sensitive values should be marked as Sensitive

Greetings,

Terraform has a nice feature that allows us to mask sensitive values in Terraform plan / apply. At the moment, this provider does not leverage that feature in the sdm_resource resource which leads us to plans that can leak sensitive values:

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # sdm_resource.bd_readonly will be updated in-place
  ~ resource "sdm_resource" "bd_readonly" {
        id = "rs-0c5b6edfc93d4a01"

      ~ mysql {
            database      = "bd"
            hostname      = "bd.random.us-east-1.rds.amazonaws.com"
            name          = "bd-readonly"
          + password      = "mySuperPassword"
            port          = 3306
            port_override = 10001
            username      = "app_sdm_ro"
        }
    }

Since Terraform is expected to run in a CI tool like Jenkins, we don't want people with access to that Jenkins instance to gain access to the database password in clear text.

The fix is simple. When declaring the resource schema, simply add Sensitive: true for each element of the schema that can be considered sensitive.

For example:

"password": {
    Type:        schema.TypeString,
    Required:    true,
    Description: "",
}

Should be:

"password": {
    Type:        schema.TypeString,
    Required:    true,
    Description: "",
    Sensitive:   true,
}

Do you want me to open a pull request with all the fixes?

Regards,
Jean-Philippe Lachance

Tags option not working for some Data Source filters

Within Data Sources "sdm_account", "sdm_node", "sdm_role", "sdm_secret_store" list "tags" as an available argument, how ever if you use tags in these, the following exception during terraform plan:
Error: Unsupported block type, Blocks of type "tags" are not expected here.

I tested with TF Provider version 2.2.0

Docs:
https://registry.terraform.io/providers/strongdm/sdm/latest/docs/data-sources/account
https://registry.terraform.io/providers/strongdm/sdm/latest/docs/data-sources/node
https://registry.terraform.io/providers/strongdm/sdm/latest/docs/data-sources/role
https://registry.terraform.io/providers/strongdm/sdm/latest/docs/data-sources/secret_store

secret store id change still doesn't force re-creation on all resource types

I was testing with Kubernetes and this issue still seems to be present for that resource type as well:

│ Error: cannot update Resource rs-6184a8866476710a: failed to update resource rs-6184a8866476710a: invalid operation: secret store does not match original resource (rs-6184a8866476710a)
│
│   with module.strongdm_eks.sdm_resource.amazon_eks_instance_profile["dev-eks-use1-admin"],
│   on ../../../../modules/strongdm/amazon_eks.tf line 26, in resource "sdm_resource" "amazon_eks_instance_profile":
│   26: resource "sdm_resource" "amazon_eks_instance_profile" {
│
╵

Can we fix this on all resource types that accept a secret store id?

Using SDM in module causes terraform to insist on trying to get non-existent "hashicorp/sdm" module

I have a module with the following resource in it:
resource "sdm_resource" "db_superuser_access" {
postgres {
name = var.sdm_resource_name_db_superuser
hostname = var.postgres_hostname
database = "postgres"
username = var.postgres_username
password = var.postgres_password
port = 5432
tags = var.strongdm_tags
}
}

There is no provider information in that module - so in my main terraform I have the SDM information
provider "sdm" {
api_access_key =
api_secret_key =
terraform {
required_providers {
sdm = {
source = "strongdm/sdm"
version = "1.0.39"
}
}
}

but every time I try to run it, it complains
│ Could not retrieve the list of available versions for provider hashicorp/sdm: provider registry registry.terraform.io does not have a provider named
│ registry.terraform.io/hashicorp/sdm

│ Did you intend to use strongdm/sdm? If so, you must specify that source address in each module which requires that provider. To see which modules are currently depending
│ on hashicorp/sdm, run the following command:
│ terraform providers

But I am telling it to use strongdm/sdm! When I type in the terraform providers command, it says that the module I'm running is insisting on hashicorp/sdm.. but there is no provider information of any kind in the module I wrote. Why is it not inheriting the sdm provider from my main terraform?

Ability to leverage existing session in SDM client

One of the reasons we use strongDM is being able to minimize the need to throw credentials around or store them on people's machines. We love the functionality of being able to integrate resources from the terraform provider into our substantial terraform codebase, but one thing that we struggled with was that the provider only accepts API keys for authentication.

While it's good that the API keys are linked back to a user to provide auditability for actions they're performing when they apply the terraform, it would be better if we could just leverage the existing session from the already authenticated sdm client (which already has the privileges to perform all of the actions that we may need to do) and avoid having to generate and store credentials entirely, greatly improving security while also simplifying the provider configuration.

Changing a port_override creates a plan that cannot be applied

  # resource will be updated in-place
  ~ resource "sdm_resource" "resource" {
        id = REDACTED
      ~ google_gke {
            name                  = REDACTED
          ~ port_override         = 10006 -> 10001
            # (5 unchanged attributes hidden)
        }
    }

Leads to

│ Error: cannot update Resource rs-$ID: failed to update resource rs-$ID: item already exists: port override already allocated

Enabling seamless downstream integration by adding a datasource that handles `sdm connect`

One of the advantages of using terraform is the ability to seamlessly integrate between different types of resources, allowing them to dynamically pass values from one to another. In our environment, we often will create modules which may create a database server, then connect to it via a tunnel and provision database credentials and grants within that server.

One thing we noticed the provider was lacking which would be very useful is a datasource that would allow us to connect to a database (e.g. by issuing sdm connect) and then outputting the port number, which we could then use to configure downstream providers to tunnel via strongDM and avoid having to store credentials or use a separate SSH tunnel for those operations.

In the meantime, I've implemented a basic external datasource that allows us to do this (source code included below in case you're interested):

The datasource definition:

data "external" "sdm_client" {
  program = [
    "sh",
    "${path.module}/scripts/client.sh"
  ]
  query = {
    datasource = "<name of strongDM datasource to connect to>"
  }
}

Here's the source for the shell script that it's calling:

QUERY="`dd 2>/dev/null`"
export DATASOURCE="`echo $QUERY | sed -e 's/^.*\"datasource\": *\"//' -e 's/\".*$//g'`"

OUTPUT="`sdm connect $DATASOURCE -v | head -n 1`"

#output an error if it is not successful
case "$OUTPUT" in
  *connected*)
    #grab the port number to use
    PORTNUMBER="`echo $OUTPUT | sed 's/^.*on port //g'`"
    echo "{\"portnumber\": \"$PORTNUMBER\"}"
    ;;
  *)
    exit 1
    ;;
esac

We can then configure the downstream mysql provider to use the datasource to perform provisioning operations like this:

provider "mysql" {
  alias    = "sdm"
  endpoint = "127.0.0.1:${data.external.sdm_client.result.portnumber}"
  username = var.root_db_user
}

resource "mysql_user" "user" {
  provider           = mysql.sdm
  depends_on         = [data.external.sdm_client]
  user               = "my_app_user"
  host               = "%"
  plaintext_password = "somepassword"
  tls_option         = "SSL"
}

Please Provide Solution to Certificate Authority parameter to google_gke

Hi,

I am using strongDM terraform provider version 1.0.20 with terraform version 0.11.15. I have the plugin downloaded and working fine with terraform version 0.11.15

Here is my code:

terraform {
  required_version = "0.11.15"

provider "sdm" { 
    #source = "strongdm/sdm" 
    version = "v1.0.20"       
}

resource "sdm_resource" "dear_s" {
    postgres {
        name =  "name"
        hostname        = "hostname.net"
        database         = "db-name"
        username        = "username"
        password        = "password"
        port                 = 2342
    }
}

resource "sdm_resource" "dear_b" {
    postgres {
         name            =  "name"
        hostname     = "hostname-2.net"
        database      = "db-name-2"
        username     = "username-2"
        password     = "password-2"
        port              = 2342
    }
}

resource "sdm_resource" "gke_cluster" {
    google_gke {
        name                               =  "cluster-name"
        endpoint                         =  "10.88.88.88"
        certificate_authority      =  "${file(./gke_cert_auth.crt)}"
        service_account_key    =  "${file(./account.json)}"
        
       
    }
}

terraform init
terraform apply

The first two resources were successfully created in strongDM UI but the last time failed to create and output the following error:

Error: Error applying plan:

1 error occurred:
        * sdm_resource.gke_cluster: cannot create Resource: error validating datasource: invalid operation: cannot validate ca cert: invalid cert block pem data

The strange thing is that I can do this successfully on strongDM UI with the same certificate authority credential.

What am I doing wrong here?

data sdm_peering_group: small bug?

Hello,

I'm working on peering groups. My current task is to update a Terraform module in charge of registering databases into StrongDM, make the resources also join a list of peering groups.

My code:

variable "peering_group_ids" {
  description = "List of StrongDM Network Peering Groups to which the database belongs."
  type        = list(string)
}

data "sdm_peering_group" "dep_1" {
  name = "dep-us-east-1-ingress"
}

data "sdm_peering_group" "dep_2" {
  name = "dep-us-east-2-ingress"
}

locals {
  peering_group_ids = concat([
    data.sdm_peering_group.dep_1.id,
    data.sdm_peering_group.dep_2.id
  ], var.peering_group_ids)
}

resource "sdm_peering_group_resource" "database" {
  for_each = toset(local.peering_group_ids)

  group_id    = each.value
  resource_id = "some-resource-id"
}

When I run a plan, I notice:

  # module.db_register_to_strongdm.sdm_peering_group_resource.database["PeeringGroupname:? dep-us-east-2-ingress"] will be created
  + resource "sdm_peering_group_resource" "database" {
      + group_id    = "PeeringGroupname:? dep-us-east-2-ingress"
      + id          = (known after apply)
      + resource_id = "some-resource-id"
    }

And when I try to apply:

│ Error: cannot create PeeringGroupResource: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp: lookup api.strongdm.com: i/o timeout"
│ 
│   with module.db_register_to_strongdm.sdm_peering_group_resource.database["PeeringGroupname:? dep-us-east-2-ingress"],
│   on .terraform/modules/db_register_to_strongdm/modules/sdm_register_mysql_database/user.tf line 204, in resource "sdm_peering_group_resource" "database":
│  204: resource "sdm_peering_group_resource" "database" {

My feeling is that the data on sdm_peering_group is not working, data.sdm_peering_group.dep_2.id is not a peering group ID.

Can someone have a look?

Thank you!

On change of load balancer, gateway update does not work

When replacing a load balancer for a gateway

Terraform plan output

  # sdm_node.gateway must be replaced
+/- resource "sdm_node" "gateway" {
      ~ id = "n-3da34a9e62016d0f" -> (known after apply)

      ~ gateway {
          ~ listen_address = "REMOVED.elb.us-east-1.amazonaws.com:443" -> (known after apply) # forces replacement
            name           = "REMOVED-1"
          ~ token          = (sensitive value)
            # (1 unchanged attribute hidden)
        }
    }

Terraform error

│ Error: cannot create Node: could not create gateway: item already exists: already exists: REMOVED-1
│
│   with sdm_node.gateway,
│   on strongdm.tf line 94, in resource "sdm_node" "gateway":
│   94: resource "sdm_node" "gateway" {

Tokens returned from gateway node resource are empty strings

Hi,

I've been working on bringing our gateways under terraform control. I've imported the gateways per the guide using their unique id (returned from sdm admin relays list):

> terraform import ...sdm_node.gateway n-xxx

The issue I'm seeing is that the gateway token is returned as an empty string.

I'm running on the latest version v2.0.0:

+ provider registry.terraform.io/strongdm/sdm v2.0.0

Gateway resource binding:

resource "sdm_node" "gateway" {
  gateway {
    name           = "dev-us-west-2-gateway-1"
    listen_address = "sdm-gateway-1.xx.yy:30001"
    bind_address   = "0.0.0.0:5000"
    tags = {
      aws_profile = "dev"
      aws_region  = "us-west-2"
    }
  }
}

I then later reference the value as sdm_node.gateway.gateway[0].token which is returning "".

Terraform Provider Development program

Hey Team,

Thanks for all the work you've put in to building this provider. There are a few items to address before we can release the provider and officially integrating it into Terraform.

The website docs you have build look great but these are a few changes to get them ready to be published with the rest of the providers on Terraform.io.

  • Each provider has a ruby layout file that defines the sidebar directory for your providers docs. You can use the Random providers random.erb as a reference. Be aware that the the Random provider uses r/ and d/ for their directory names.
  • The files structure needs to be changed to follow our standard structure.
-website/
    -sdm.erb
    -docs
        -index.html
        -resources/ 
        -data-sources/
        -guides/
  • Each markdown file should container the postfix .html.md or .html.markdown so that they can be sync with our middleman tool that builds the website.
  • There are two additional lines that need to be added to each documentation page. Layout and sidebar_current should align with the sdm.erb links. I.e. the following lines should be added to account.md.
layout: “sdm”
sidebar_current: “docs-sdm-resource-account”
  • This GNUmakefile is standard across all Terraform providers, feel free to copy the Random provider makefile and will just have to update the variable on line 4 to PKG_NAME=sdm

  • There are four bash scripts kept in a scripts/ directory that are used in different processes of testing and release, these can all be copied from the Random provider

  • You are already using Go Modules to manage the providers dependancies which is great, but in addition to that, we require that all dependancies are checked into a vendor/ directory. This can be done by running go mod vendor.

  • Each Terraform provider must have a CHANGELOG that is updated during reach release. Since the changeling is updated by a bot during the release it must be in a certain format. With the AWS provider changelog as an example, the version of the next release should be tagged as “1.0.0 (Unreleased)” and will then be updated with a date by the release-bot. The version number is up to you but should follow semantic version practices.

  • All providers have a TravisCI check with unit tests on each PR that is opened. Can you please add a .travis.yaml file to make the standard configuration

  • One of our Terraform ecosystem engineers built a linter that helps align coding best practices for providers. You should use it along with your development. https://github.com/bflad/tfproviderlint

Once all these item are addressed we can start the final phase of the partner provider program which will be preformed by myself and another HashiCorp engineer.

  • A repository under the same name terraform-providers-sdm will be created in the github.com/terraform-repositories/ organization.
  • Your provider code will be pushed up to the new repository
  • Binaries will be built for the following distributions and architectures.
    linux: 386; amd64; arm
    freebsd: 386; amd64; arm
    openbsd: 386; amd64
    windows: amd64; 386
    darwin: amd64
    solaris: amd64
  • A stable-website branch will be created, this is where the terraform.io provider documentation is source from. During each release, a bot will commit the changes in your master branch to the stable-website branch. If you need to make changes to the provider website docs in between releases, you can cherry-pick the commits to the stable-website branch.
  • The first release will be tagged as per your CHANGELOG.md
  • You and whomever else on your team will be granted “write” access over the new repository are you are still seen as the owners and maintainers of the provider, before I grant you access, you’ll must review and agree to our community guidelines, which I’ll include below.
  • Whomever is added as a maintainer to the provider repository will also be granted an account on our #committers-terraform Slack channel, where you will request new versioned releases of the provider.

Please let me know if you have any questions.

Please add support for multiple roles and/or temporary access grants

Hi,

I'm using the SDM provider v1.0.16 to provision server SSH resources for adhoc dev boxes in AWS. Each user is assigned a devbox which creates a server SSH profile in SDM. Ideally, we'd directly assign the server to the user via. an account_grant or role_grant. However this fails as SDM only allows a user to have a single role assigned (would be nice to relax this). To work around this we leverage temporary access grants but these aren't supported via. the SDM provider.

We're currently using a provisioner local-exec step that calls grant-temporary to workaround this:

// devboxes = ['[email protected]', '[email protected]', ...]
resource "sdm_resource" "devbox" {
  for_each = var.devboxes

  ssh {
    name            = "devbox-${each.value}"
    hostname        = aws_network_interface.this[each.value].private_ip
    username        = var.ssh_username
    port            = 22
    port_forwarding = true
  }

  provisioner "local-exec" {
    command = "sdm admin users grant-temporary --until=2030-01-01T00:00:00+07:00 devbox-${each.value} ${each.value} --force"
  }
}

While this works, it requires the invoking user to have both sdm, be logged in, and be in an admin role.

Ask:

  • allow users to be members of multiple roles -- this would require no changes in the SDM provider
  • add support for granting temporary access to the SDM provider

Thanks,
Nigel.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.