Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support testing API key as part of provider setup #118

Closed
yi2020 opened this issue Jan 8, 2021 · 1 comment
Closed

Support testing API key as part of provider setup #118

yi2020 opened this issue Jan 8, 2021 · 1 comment

Comments

@yi2020
Copy link
Contributor

yi2020 commented Jan 8, 2021

We use restapi as part of the template we provide our users. The template created a role for our Cloudrail product, then makes an API call to our backend to add the cloud account automatically. This works well (I've included the contents of the template at the end here for reference).

We have a need though: we want to check that the API key the user provided is valid before starting. We thought of using a data source for this, but that would be a bit of a square-peg-round-hole kind of thing. So, the idea came up that the provider would be able to test the API key upon initialization.

Basically, there would be a provider parameter (that is empty by default), which includes an API path to call upon initialization to see that the API key and everything is working well. Something like this:

provider "restapi" {
  uri = "https://api.cloudrail.app"
  headers = {
    "X-Api-Key": var.cloudrail-api-key
  }
  write_returns_object = true
  test_path = "/hello" # Upon init, restapi will hit https://api.cloudrail.app/hello with the X-Api-Key and expect a 200 response
}

I'm happy to work on the implementation myself. @DRuggeri just let me know this is an OK suggestion by you and I'll prepare a PR.

For reference, here's the full Terraform file we supply our users:

terraform {
  required_providers {
    restapi = {
      source  = "fmontezuma/restapi"
      version = "~> 1.14.0"
    }
  }
}

variable "cloudrail-api-key" {
  type        = string
  description = "The Cloudrail API key."
}

variable "account-name" {
  type        = string
  description = "The name of the AWS account you're adding. This name will be displayed in the Cloudrail user interface."
}

provider "aws" {
  region = "us-east-1"
}

provider "restapi" {
  uri = "https://api.cloudrail.app"
  headers = {
    "X-Api-Key": var.cloudrail-api-key
  }
  write_returns_object = true # This means that when we POST the account we will get back the object that was created, with an "id"
}

data "aws_caller_identity" "current" {}

resource "aws_iam_role" "cloudrail_role" {
  name        = "cloudrail-viewonly-jyvidfxltrza-role"
  description = "This role is used by Cloudrail to access this account and collect information on resources configured. Cloudrail does not make any modifications."

  assume_role_policy = <<-EOF
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "645376637575"
          },
          "Action": "sts:AssumeRole",
          "Condition": {
            "StringEquals": {
              "sts:ExternalId": "hjgjthvhghac"
            }
          }
        }
      ]
    }
    EOF
}

data "aws_iam_policy" "aws_viewonly_access" {
  arn = "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"
}

data "aws_iam_policy" "aws_security_audit" {
  arn = "arn:aws:iam::aws:policy/SecurityAudit"
}

resource "aws_iam_role_policy_attachment" "cloudrail_viewonly_attach_policy" {
  role       = aws_iam_role.cloudrail_role.name
  policy_arn = data.aws_iam_policy.aws_viewonly_access.arn
}

resource "aws_iam_role_policy_attachment" "cloudrail_security_audit_attach_policy" {
  role       = aws_iam_role.cloudrail_role.name
  policy_arn = data.aws_iam_policy.aws_security_audit.arn
}

# Sleep needed before making API call
resource "time_sleep" "wait_5_seconds" {
  depends_on = [aws_iam_role.cloudrail_role, aws_iam_role_policy_attachment.cloudrail_viewonly_attach_policy, aws_iam_role_policy_attachment.cloudrail_security_audit_attach_policy]

  create_duration = "5s"
}

resource "restapi_object" "account_in_cloudrail" {
  path = "/accounts"
  data = jsonencode(
    {
      "name": var.account-name,
      "cloud_account_id": data.aws_caller_identity.current.account_id,
      "interval_seconds": 3600
    }
    )
  depends_on = [time_sleep.wait_5_seconds]
}
@DRuggeri
Copy link
Member

Thanks for the idea, @yi2020! Yeah, this sounds like something worth including. I really appreciate the offer to add the code via PR, but since I was in the neighborhood cleaning some things up, I just added this to the provider in and will release it soon. Thanks for the idea!

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

No branches or pull requests

2 participants