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

feat: Authenticate Digital Ocean via environment variable #2051

Merged
merged 3 commits into from
Jun 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 36 additions & 2 deletions docs/templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ vim <template-name>/main.tf
coder templates <create/update> <template-name>
```

> We recommend source controlling your templates.

## Persistent and ephemeral resources

Coder supports both ephemeral and persistent resources in workspaces. Ephemeral
Expand Down Expand Up @@ -53,6 +51,42 @@ Templates often contain *parameters*. In Coder, there are two types of parameter
each workspace, often personalization settings such as "preferred
region" or "workspace image".


## Best Practices

### Template Changes

We recommend source controlling your templates.

### Authenticating with Cloud Providers

Coder's provisioner process needs to authenticate with cloud provider APIs to provision
workspaces. We strongly advise against including credentials directly in your templates. You
can either pass credentials to the provisioner as parameters, or execute Coder
in an environment that is authenticated with the cloud provider.

We encourage the latter where supported. This approach simplifies the template, keeps cloud
provider credentials out of Coder's database (making it a less valuable target for attackers),
and is compatible with agent-based authentication schemes (that handle credential rotation
and/or ensure the credentials are not written to disk).

Cloud providers for which the Terraform provider supports authenticated environments include

* [Google Cloud](https://registry.terraform.io/providers/hashicorp/google/latest/docs)
* [Amazon Web Services](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)
* [Microsoft Azure](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)
* [Kubernetes](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs)

Additional providers may be supported; check the
[documentation of the Terraform provider](https://registry.terraform.io/browse/providers) for
details.

The way these generally work is via the credentials being available to Coder either in some
well-known location on disk (e.g. `~/.aws/credentials` for AWS on posix systems), or via
environment variables. It is usually sufficient to authenticate using the CLI or SDK for the
cloud provider before running Coder for this to work, but check the Terraform provider
documentation for details.

---

Next: [Workspaces](./workspaces.md)
7 changes: 7 additions & 0 deletions examples/templates/aws-linux/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ tags: [cloud, aws]

Pick this template in `coder templates init` and follow instructions.

## Authentication

This template assumes that coderd is run in an environment that is authenticated
with AWS. For example, run `aws configure import` to import credentials on the
system and user running coderd. For other ways to authenticate [consult the
Terraform docs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#authentication-and-configuration).

## Required permissions / policy

This example policy allows Coder to create EC2 instances and modify instances provisioned by Coder.
Expand Down
24 changes: 1 addition & 23 deletions examples/templates/aws-linux/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,6 @@ terraform {
}
}

variable "access_key" {
description = <<EOT
Create an AWS access key to provision resources with Coder:
- https://console.aws.amazon.com/iam/home#/users

See the template README for an example permissions policy,
if needed.

AWS Access Key ID
EOT
sensitive = true
}

variable "secret_key" {
description = <<EOT
AWS Secret Key
EOT
sensitive = true
}

# Last updated 2022-05-31
# aws ec2 describe-regions | jq -r '[.Regions[].RegionName] | sort'
variable "region" {
Expand Down Expand Up @@ -70,9 +50,7 @@ variable "disk_size" {
}

provider "aws" {
region = var.region
access_key = var.access_key
secret_key = var.secret_key
region = var.region
}

data "coder_workspace" "me" {
Expand Down
66 changes: 66 additions & 0 deletions examples/templates/aws-windows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,69 @@ name: Develop in Windows on AWS
description: Get started with Windows development on AWS.
tags: [cloud, aws]
---

# aws-windows

## Getting started

Pick this template in `coder templates init` and follow instructions.

## Authentication

This template assumes that coderd is run in an environment that is authenticated
with AWS. For example, run `aws configure import` to import credentials on the
system and user running coderd. For other ways to authenticate [consult the
Terraform docs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#authentication-and-configuration).

## Required permissions / policy

This example policy allows Coder to create EC2 instances and modify instances provisioned by Coder.

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:GetDefaultCreditSpecification",
"ec2:DescribeIamInstanceProfileAssociations",
"ec2:DescribeTags",
"ec2:CreateTags",
"ec2:RunInstances",
"ec2:DescribeInstanceCreditSpecifications",
"ec2:DescribeImages",
"ec2:ModifyDefaultCreditSpecification",
"ec2:DescribeVolumes"
],
"Resource": "*"
},
{
"Sid": "CoderResouces",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeInstanceAttribute",
"ec2:UnmonitorInstances",
"ec2:TerminateInstances",
"ec2:StartInstances",
"ec2:StopInstances",
"ec2:DeleteTags",
"ec2:MonitorInstances",
"ec2:CreateTags",
"ec2:RunInstances",
"ec2:ModifyInstanceAttribute",
"ec2:ModifyInstanceCreditSpecification"
],
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/Coder_Provisioned": "true"
}
}
}
]
}
```

21 changes: 1 addition & 20 deletions examples/templates/aws-windows/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,6 @@ terraform {
}
}

variable "access_key" {
description = <<EOT
Create an AWS access key to provision resources with Coder:
- https://console.aws.amazon.com/iam/home#/users

AWS Access Key
EOT
sensitive = true
}

variable "secret_key" {
description = <<EOT
AWS Secret Key
EOT
sensitive = true
}

# Last updated 2022-05-31
# aws ec2 describe-regions | jq -r '[.Regions[].RegionName] | sort'
variable "region" {
Expand Down Expand Up @@ -54,9 +37,7 @@ variable "region" {
}

provider "aws" {
region = var.region
access_key = var.access_key
secret_key = var.secret_key
region = var.region
}

data "coder_workspace" "me" {
Expand Down
10 changes: 9 additions & 1 deletion examples/templates/do-linux/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,16 @@ This is an example for deploying workspaces as Digital Ocean Droplets.

## Requirements

- Digital Ocean Personal Access Token (PAT)
- Digital Ocean Project ID (e.g. `doctl projects list`)
- Remove `variable "step2_do_project_id"` and `resource "digitalocean_project_resources" "project"` if you don't want project association.
- (Optional) Digital Ocean SSH key ID (e.g. `doctl compute ssh-key list`)
- Only required for Fedora images to work.

## Authentication

This template assumes that coderd is run in an environment that is authenticated
with Digital Ocean. Obtain a
[Digital Ocean Personal Access Token](https://cloud.digitalocean.com/account/api/tokens) and set
the environment variable `DIGITALOCEAN_TOKEN` to the access token before starting coderd. For
other ways to authenticate
[consult the Terraform docs](https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs).
28 changes: 9 additions & 19 deletions examples/templates/do-linux/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,7 @@ terraform {
}
}

variable "step1_do_token" {
type = string
description = "Enter token (see documentation at https://docs.digitalocean.com/reference/api/create-personal-access-token/)"
sensitive = true

validation {
condition = length(var.step1_do_token) == 71 && substr(var.step1_do_token, 0, 4) == "dop_"
error_message = "Invalid Digital Ocean Personal Access Token."
}
}

variable "step2_do_project_id" {
variable "step1_do_project_id" {
type = string
description = <<-EOF
Enter project ID
Expand All @@ -32,17 +21,17 @@ variable "step2_do_project_id" {
sensitive = true

validation {
condition = length(var.step2_do_project_id) == 36
condition = length(var.step1_do_project_id) == 36
error_message = "Invalid Digital Ocean Project ID."
}
}

variable "step3_do_admin_ssh_key" {
variable "step2_do_admin_ssh_key" {
type = number
description = <<-EOF
Enter admin SSH key ID (some Droplet images require an SSH key to be set):

Can be set to zero.
Can be set to "0" for no key.

Note: Setting this to zero will break Fedora images and notify root passwords via email.

Expand All @@ -51,7 +40,7 @@ variable "step3_do_admin_ssh_key" {
sensitive = true

validation {
condition = var.step3_do_admin_ssh_key >= 0
condition = var.step2_do_admin_ssh_key >= 0
error_message = "Invalid Digital Ocean SSH key ID, a number is required."
}
}
Expand Down Expand Up @@ -98,7 +87,8 @@ variable "region" {

# Configure the DigitalOcean Provider
provider "digitalocean" {
token = var.step1_do_token
# Recommended: use environment variable DIGITALOCEAN_TOKEN with your personal access token when starting coderd
# alternatively, you can pass the token via a variable.
}

data "coder_workspace" "me" {}
Expand Down Expand Up @@ -130,12 +120,12 @@ resource "digitalocean_droplet" "workspace" {
coder_agent_token = coder_agent.dev.token
})
# Required to provision Fedora.
ssh_keys = var.step3_do_admin_ssh_key > 0 ? [var.step3_do_admin_ssh_key] : []
ssh_keys = var.step2_do_admin_ssh_key > 0 ? [var.step2_do_admin_ssh_key] : []
}

# Temporarily disabled because it breaks SSH. (https://github.com/coder/coder/issues/1750)
# resource "digitalocean_project_resources" "project" {
# project = var.step2_do_project_id
# project = var.step1_do_project_id
# # Workaround for terraform plan when using count.
# resources = length(digitalocean_droplet.workspace) > 0 ? [
# digitalocean_volume.home_volume.urn,
Expand Down
19 changes: 19 additions & 0 deletions examples/templates/gcp-linux/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,22 @@ name: Develop in Linux on Google Cloud
description: Get started with Linux development on Google Cloud.
tags: [cloud, google]
---

# gcp-linux

## Getting started

Pick this template in `coder templates init` and follow instructions.

## Authentication

This template assumes that coderd is run in an environment that is authenticated
with Google Cloud. For example, run `gcloud auth application-default login` to import
Comment on lines +15 to +16
Copy link
Member

@bpmct bpmct Jun 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think calling it coderd is unclear in this case. This was the name for the Coder binary in Coder Classic, but we don't refer to it as coderd in the user-facing product UI or documentation. I'd suggest calling it the "Coder host"

I did notice the code refers to it as "coderd"

Would like your thoughts though. We can merge and reconsider later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a consistent set of terms for various components of the project / solution, and for v1 stuff moving forward (are we calling this "Coder Classic"!?). Perhaps you and I can collaborate on a RFC to this effect and get some more input.

It's really a drag to have different internal and external names down at the component level. Engineers will naturally screw up terminology in documents, customer interactions, etc. So, there has to be a really strong case for naming these things differently.

credentials on the system and user running coderd. For other ways to authenticate
[consult the Terraform docs](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/getting_started#adding-credentials).

## Required permissions / policy

The user or service account used by the Terraform provisioner should have the following roles

- Compute Admin
21 changes: 4 additions & 17 deletions examples/templates/gcp-linux/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,8 @@ terraform {
}
}

variable "service_account" {
description = <<EOF
Coder requires a Google Cloud Service Account to provision workspaces.

1. Create a service account:
https://console.cloud.google.com/projectselector/iam-admin/serviceaccounts/create
2. Add the roles:
- Compute Admin
- Service Account User
3. Click on the created key, and navigate to the "Keys" tab.
4. Click "Add key", then "Create new key".
5. Generate a JSON private key, and paste the contents below.
EOF
sensitive = true
variable "project_id" {
description = "Which Google Compute Project should your workspace live in?"
}

variable "zone" {
Expand All @@ -37,9 +25,8 @@ variable "zone" {
}

provider "google" {
zone = var.zone
credentials = var.service_account
project = jsondecode(var.service_account).project_id
zone = var.zone
project = var.project_id
}

data "google_compute_default_service_account" "default" {
Expand Down
19 changes: 19 additions & 0 deletions examples/templates/gcp-vm-container/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,22 @@ name: Develop in a container on a Google Cloud VM
description: Get started with Linux development on Google Cloud.
tags: [cloud, google, container]
---

# gcp-vm-container

## Getting started

Pick this template in `coder templates init` and follow instructions.

## Authentication

This template assumes that coderd is run in an environment that is authenticated
with Google Cloud. For example, run `gcloud auth application-default login` to import
credentials on the system and user running coderd. For other ways to authenticate
[consult the Terraform docs](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/getting_started#adding-credentials).

## Required permissions / policy

The user or service account used by the Terraform provisioner should have the following roles

- Compute Admin