diff --git a/.github/workflows/update-readme.yaml b/.github/workflows/update-readme.yaml index ffda695..0d0e226 100644 --- a/.github/workflows/update-readme.yaml +++ b/.github/workflows/update-readme.yaml @@ -9,7 +9,7 @@ on: jobs: update-readme: permissions: - contents: read + contents: write pull-requests: write runs-on: ubuntu-latest steps: @@ -33,6 +33,7 @@ jobs: title: 'chore: bump version to ${{ env.TAG }} in README.md files' body: 'This is an auto-generated PR to update README.md files of all modules with the new tag ${{ env.TAG }}' branch: 'update-readme-branch' + base: 'main' env: TAG: ${{ steps.get-latest-tag.outputs.TAG }} diff --git a/.images/hcp-vault-secrets-credentials.png b/.images/hcp-vault-secrets-credentials.png new file mode 100644 index 0000000..e5e9cf2 Binary files /dev/null and b/.images/hcp-vault-secrets-credentials.png differ diff --git a/code-server/main.tf b/code-server/main.tf index 86afdd0..b45d4fe 100644 --- a/code-server/main.tf +++ b/code-server/main.tf @@ -32,6 +32,12 @@ variable "display_name" { default = "code-server" } +variable "slug" { + type = string + description = "The slug for the code-server application." + default = "code-server" +} + variable "settings" { type = map(string) description = "A map of settings to apply to code-server." @@ -89,7 +95,7 @@ resource "coder_script" "code-server" { resource "coder_app" "code-server" { agent_id = var.agent_id - slug = "code-server" + slug = var.slug display_name = var.display_name url = "http://localhost:${var.port}/${var.folder != "" ? "?folder=${urlencode(var.folder)}" : ""}" icon = "/icon/code.svg" diff --git a/filebrowser/README.md b/filebrowser/README.md index e783588..781e122 100644 --- a/filebrowser/README.md +++ b/filebrowser/README.md @@ -14,7 +14,7 @@ A file browser for your workspace. ```tf module "filebrowser" { source = "registry.coder.com/modules/filebrowser/coder" - version = "1.0.2" + version = "1.0.3" agent_id = coder_agent.example.id } ``` @@ -28,7 +28,7 @@ module "filebrowser" { ```tf module "filebrowser" { source = "registry.coder.com/modules/filebrowser/coder" - version = "1.0.2" + version = "1.0.3" agent_id = coder_agent.example.id folder = "/home/coder/project" } @@ -39,7 +39,7 @@ module "filebrowser" { ```tf module "filebrowser" { source = "registry.coder.com/modules/filebrowser/coder" - version = "1.0.2" + version = "1.0.3" agent_id = coder_agent.example.id database_path = ".config/filebrowser.db" } diff --git a/git-commit-signing/README.md b/git-commit-signing/README.md index b3e3b67..ada6110 100644 --- a/git-commit-signing/README.md +++ b/git-commit-signing/README.md @@ -19,7 +19,7 @@ This module has a chance of conflicting with the user's dotfiles / the personali ```tf module "git-commit-signing" { source = "registry.coder.com/modules/git-commit-signing/coder" - version = "1.0.2" + version = "1.0.3" agent_id = coder_agent.example.id } ``` diff --git a/hcp-vault-secrets/README.md b/hcp-vault-secrets/README.md index c45cff6..377ad5a 100644 --- a/hcp-vault-secrets/README.md +++ b/hcp-vault-secrets/README.md @@ -23,7 +23,14 @@ module "vault" { ## Configuration -To configure the HCP Vault Secrets module, you must create an HCP Service Principal from the HCP Vault Secrets app in the HCP console. This will give you the `HCP_CLIENT_ID` and `HCP_CLIENT_SECRET` that you need to authenticate with HCP Vault Secrets. See the [HCP Vault Secrets documentation](https://developer.hashicorp.com/hcp/docs/vault-secrets) for more information. +To configure the HCP Vault Secrets module, follow these steps, + +1. [Create secrets in HCP Vault Secrets](https://developer.hashicorp.com/vault/tutorials/hcp-vault-secrets-get-started/hcp-vault-secrets-create-secret) +2. Create an HCP Service Principal from the HCP Vault Secrets app in the HCP console. This will give you the `HCP_CLIENT_ID` and `HCP_CLIENT_SECRET` that you need to authenticate with HCP Vault Secrets. + ![HCP vault secrets credentials](../.images/hcp-vault-secrets-credentials.png) +3. Set `HCP_CLIENT_ID` and `HCP_CLIENT_SECRET` variables on the coder provisioner (recommended) or supply them as input to the module. + +> See the [HCP Vault Secrets documentation](https://developer.hashicorp.com/hcp/docs/vault-secrets) for more information. ## Fetch All Secrets diff --git a/jetbrains-gateway/README.md b/jetbrains-gateway/README.md index a176fc9..629f850 100644 --- a/jetbrains-gateway/README.md +++ b/jetbrains-gateway/README.md @@ -14,7 +14,7 @@ This module adds a JetBrains Gateway Button to open any workspace with a single ```tf module "jetbrains_gateway" { source = "registry.coder.com/modules/jetbrains-gateway/coder" - version = "1.0.2" + version = "1.0.3" agent_id = coder_agent.example.id agent_name = "example" folder = "/home/coder/example" @@ -32,7 +32,7 @@ module "jetbrains_gateway" { ```tf module "jetbrains_gateway" { source = "registry.coder.com/modules/jetbrains-gateway/coder" - version = "1.0.2" + version = "1.0.3" agent_id = coder_agent.example.id agent_name = "example" folder = "/home/coder/example" diff --git a/jfrog-oauth/main.tf b/jfrog-oauth/main.tf index 9f05e56..70fd0e8 100644 --- a/jfrog-oauth/main.tf +++ b/jfrog-oauth/main.tf @@ -19,6 +19,12 @@ variable "jfrog_url" { } } +variable "jfrog_server_id" { + type = string + description = "The server ID of the JFrog instance for JFrog CLI configuration" + default = "0" +} + variable "username_field" { type = string description = "The field to use for the artifactory username. i.e. Coder username or email." @@ -79,6 +85,7 @@ resource "coder_script" "jfrog" { script = templatefile("${path.module}/run.sh", { JFROG_URL : var.jfrog_url, JFROG_HOST : local.jfrog_host, + JFROG_SERVER_ID : var.jfrog_server_id, ARTIFACTORY_USERNAME : local.username, ARTIFACTORY_EMAIL : data.coder_workspace.me.owner_email, ARTIFACTORY_ACCESS_TOKEN : data.coder_external_auth.jfrog.access_token, diff --git a/jfrog-oauth/run.sh b/jfrog-oauth/run.sh index c0fa589..2a7b0d1 100644 --- a/jfrog-oauth/run.sh +++ b/jfrog-oauth/run.sh @@ -15,9 +15,9 @@ fi # flows. export CI=true # Authenticate JFrog CLI with Artifactory. -echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" --overwrite 0 +echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" --overwrite "${JFROG_SERVER_ID}" # Set the configured server as the default. -jf c use 0 +jf c use "${JFROG_SERVER_ID}" # Configure npm to use the Artifactory "npm" repository. if [ -z "${REPOSITORY_NPM}" ]; then diff --git a/jfrog-token/main.tf b/jfrog-token/main.tf index 7e63649..1caca4d 100644 --- a/jfrog-token/main.tf +++ b/jfrog-token/main.tf @@ -23,6 +23,12 @@ variable "jfrog_url" { } } +variable "jfrog_server_id" { + type = string + description = "The server ID of the JFrog instance for JFrog CLI configuration" + default = "0" +} + variable "artifactory_access_token" { type = string description = "The admin-level access token to use for JFrog." @@ -112,6 +118,7 @@ resource "coder_script" "jfrog" { script = templatefile("${path.module}/run.sh", { JFROG_URL : var.jfrog_url, JFROG_HOST : local.jfrog_host, + JFROG_SERVER_ID : var.jfrog_server_id, ARTIFACTORY_USERNAME : local.username, ARTIFACTORY_EMAIL : data.coder_workspace.me.owner_email, ARTIFACTORY_ACCESS_TOKEN : artifactory_scoped_token.me.access_token, diff --git a/jfrog-token/run.sh b/jfrog-token/run.sh index 629a65d..52b3513 100644 --- a/jfrog-token/run.sh +++ b/jfrog-token/run.sh @@ -15,9 +15,9 @@ fi # flows. export CI=true # Authenticate JFrog CLI with Artifactory. -echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" --overwrite 0 +echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" --overwrite "${JFROG_SERVER_ID}" # Set the configured server as the default. -jf c use 0 +jf c use "${JFROG_SERVER_ID}" # Configure npm to use the Artifactory "npm" repository. if [ -z "${REPOSITORY_NPM}" ]; then diff --git a/update-version.sh b/update-version.sh index 433f614..5deb63b 100755 --- a/update-version.sh +++ b/update-version.sh @@ -8,14 +8,7 @@ set -euo pipefail current_tag=$(git describe --tags --abbrev=0) previous_tag=$(git describe --tags --abbrev=0 $current_tag^) -mapfile -t changed_files < <(git diff --name-only "$previous_tag" "$current_tag" | xargs dirname | sort -u | grep -v '^\.') - -changed_dirs=() -for file in $changed_files; do - dir=$(dirname "$file") - changed_dirs+=("$dir") -done -changed_dirs=($(printf "%s\n" "${changed_dirs[@]}" | sort -u)) +mapfile -t changed_dirs < <(git diff --name-only "$previous_tag"..."$current_tag" -- ':!**/README.md' ':!**/*.test.ts' | xargs dirname | grep -v '^\.' | sort -u) LATEST_TAG=$(git describe --abbrev=0 --tags | sed 's/^v//') || exit $? @@ -33,4 +26,4 @@ for dir in "${changed_dirs[@]}"; do } }' "$file" > "$tmpfile" && mv "$tmpfile" "$file" fi -done \ No newline at end of file +done diff --git a/vault-github/README.md b/vault-github/README.md index 6919d8a..190a4a7 100644 --- a/vault-github/README.md +++ b/vault-github/README.md @@ -15,7 +15,7 @@ This module lets you authenticate with [Hashicorp Vault](https://www.vaultprojec ```tf module "vault" { source = "registry.coder.com/modules/vault-github/coder" - version = "1.0.3" + version = "1.0.4" agent_id = coder_agent.example.id vault_addr = "https://vault.example.com" } @@ -46,7 +46,7 @@ To configure the Vault module, you must set up a Vault GitHub auth method. See t ```tf module "vault" { source = "registry.coder.com/modules/vault-github/coder" - version = "1.0.3" + version = "1.0.4" agent_id = coder_agent.example.id vault_addr = "https://vault.example.com" coder_github_auth_id = "my-github-auth-id" @@ -58,7 +58,7 @@ module "vault" { ```tf module "vault" { source = "registry.coder.com/modules/vault-github/coder" - version = "1.0.3" + version = "1.0.4" agent_id = coder_agent.example.id vault_addr = "https://vault.example.com" coder_github_auth_id = "my-github-auth-id" @@ -71,7 +71,7 @@ module "vault" { ```tf module "vault" { source = "registry.coder.com/modules/vault-github/coder" - version = "1.0.3" + version = "1.0.4" agent_id = coder_agent.example.id vault_addr = "https://vault.example.com" vault_cli_version = "1.15.0" diff --git a/vault-github/run.sh b/vault-github/run.sh index 0f54a95..13f871e 100644 --- a/vault-github/run.sh +++ b/vault-github/run.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash # Convert all templated variables to shell variables INSTALL_VERSION=${INSTALL_VERSION} @@ -20,7 +20,7 @@ fetch() { fi } -unzip() { +unzip_safe() { if command -v unzip > /dev/null 2>&1; then command unzip "$@" elif command -v busybox > /dev/null 2>&1; then @@ -31,57 +31,68 @@ unzip() { fi } -# Fetch the latest version of Vault if INSTALL_VERSION is 'latest' -if [ "$${INSTALL_VERSION}" = "latest" ]; then - LATEST_VERSION=$(curl -s https://releases.hashicorp.com/vault/ | grep -oP 'vault/\K[0-9]+\.[0-9]+\.[0-9]+' | sort -V | tail -n 1) - printf "Latest version of Vault is %s.\n\n" "$${LATEST_VERSION}" - if [ -z "$${LATEST_VERSION}" ]; then - printf "Failed to determine the latest Vault version.\n" - exit 1 +install() { + # Fetch the latest version of Vault if INSTALL_VERSION is 'latest' + if [ "$${INSTALL_VERSION}" = "latest" ]; then + LATEST_VERSION=$(curl -s https://releases.hashicorp.com/vault/ | grep -v '-rc' | grep -oP 'vault/\K[0-9]+\.[0-9]+\.[0-9]+' | sort -V | tail -n 1) + printf "Latest version of Vault is %s.\n\n" "$${LATEST_VERSION}" + if [ -z "$${LATEST_VERSION}" ]; then + printf "Failed to determine the latest Vault version.\n" + return 1 + fi + INSTALL_VERSION=$${LATEST_VERSION} fi - VERSION=$${LATEST_VERSION} -fi -# Check if the vault CLI is installed and has the correct version -installation_needed=1 -if command -v vault > /dev/null 2>&1; then - CURRENT_VERSION=$(vault version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') - if [ "$${CURRENT_VERSION}" = "$${INSTALL_VERSION}" ]; then - printf "Vault version %s is already installed and up-to-date.\n\n" "$${CURRENT_VERSION}" - installation_needed=0 + # Check if the vault CLI is installed and has the correct version + installation_needed=1 + if command -v vault > /dev/null 2>&1; then + CURRENT_VERSION=$(vault version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') + if [ "$${CURRENT_VERSION}" = "$${INSTALL_VERSION}" ]; then + printf "Vault version %s is already installed and up-to-date.\n\n" "$${CURRENT_VERSION}" + installation_needed=0 + fi fi -fi -if [ $${installation_needed} -eq 1 ]; then - # Download and install Vault - if [ -z "$${CURRENT_VERSION}" ]; then - printf "Installing Vault CLI ...\n\n" - else - printf "Upgrading Vault CLI from version %s to %s ...\n\n" "$${CURRENT_VERSION}" "$${VERSION}" - fi - fetch vault.zip "https://releases.hashicorp.com/vault/$${VERSION}/vault_$${VERSION}_linux_amd64.zip" - if [ $? -ne 0 ]; then - printf "Failed to download Vault.\n" - exit 1 - fi - unzip vault.zip - if [ $? -ne 0 ]; then - printf "Failed to unzip Vault.\n" - exit 1 - fi - rm vault.zip - if sudo mv vault /usr/local/bin/vault 2> /dev/null; then - printf "Vault installed successfully!\n\n" - else - mkdir -p ~/.local/bin - mv vault ~/.local/bin/vault - if [ ! -f ~/.local/bin/vault ]; then - printf "Failed to move Vault to local bin.\n" - exit 1 + if [ $${installation_needed} -eq 1 ]; then + # Download and install Vault + if [ -z "$${CURRENT_VERSION}" ]; then + printf "Installing Vault CLI ...\n\n" + else + printf "Upgrading Vault CLI from version %s to %s ...\n\n" "$${CURRENT_VERSION}" "${INSTALL_VERSION}" + fi + fetch vault.zip "https://releases.hashicorp.com/vault/$${INSTALL_VERSION}/vault_$${INSTALL_VERSION}_linux_amd64.zip" + if [ $? -ne 0 ]; then + printf "Failed to download Vault.\n" + return 1 + fi + if ! unzip_safe vault.zip; then + printf "Failed to unzip Vault.\n" + return 1 + fi + rm vault.zip + if sudo mv vault /usr/local/bin/vault 2> /dev/null; then + printf "Vault installed successfully!\n\n" + else + mkdir -p ~/.local/bin + if ! mv vault ~/.local/bin/vault; then + printf "Failed to move Vault to local bin.\n" + return 1 + fi + printf "Please add ~/.local/bin to your PATH to use vault CLI.\n" fi - printf "Please add ~/.local/bin to your PATH to use vault CLI.\n" fi + return 0 +} + +TMP=$(mktemp -d) +if ! ( + cd "$TMP" + install +); then + echo "Failed to install Vault CLI." + exit 1 fi +rm -rf "$TMP" # Authenticate with Vault printf "🔑 Authenticating with Vault ...\n\n" diff --git a/vault-token/README.md b/vault-token/README.md new file mode 100644 index 0000000..32f5185 --- /dev/null +++ b/vault-token/README.md @@ -0,0 +1,83 @@ +--- +display_name: Hashicorp Vault Integration (Token) +description: Authenticates with Vault using Token +icon: ../.icons/vault.svg +maintainer_github: coder +partner_github: hashicorp +verified: true +tags: [helper, integration, vault, token] +--- + +# Hashicorp Vault Integration (Token) + +This module lets you authenticate with [Hashicorp Vault](https://www.vaultproject.io/) in your Coder workspaces using a [Vault token](https://developer.hashicorp.com/vault/docs/auth/token). + +```tf +variable "vault_token" { + type = string + description = "The Vault token to use for authentication." + sensitive = true +} + +module "vault" { + source = "registry.coder.com/modules/vault-token/coder" + version = "1.0.4" + agent_id = coder_agent.example.id + vault_token = var.token + vault_addr = "https://vault.example.com" +} +``` + +Then you can use the Vault CLI in your workspaces to fetch secrets from Vault: + +```shell +vault kv get -namespace=coder -mount=secrets coder +``` + +or using the Vault API: + +```shell +curl -H "X-Vault-Token: ${VAULT_TOKEN}" -X GET "${VAULT_ADDR}/v1/coder/secrets/data/coder" +``` + +## Configuration + +To configure the Vault module, you must create a Vault token with the the required permissions and configure the module with the token and Vault address. + +1. Create a vault policy with read access to the secret mount you need your developers to access. + ```shell + vault policy write read-coder-secrets - < { + await runTerraformInit(import.meta.dir); + + testRequiredVariables(import.meta.dir, { + agent_id: "foo", + vault_addr: "foo", + vault_token: "foo", + }); +}); diff --git a/vault-token/main.tf b/vault-token/main.tf new file mode 100644 index 0000000..94517d1 --- /dev/null +++ b/vault-token/main.tf @@ -0,0 +1,62 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + coder = { + source = "coder/coder" + version = ">= 0.12.4" + } + } +} + +# Add required variables for your modules and remove any unneeded variables +variable "agent_id" { + type = string + description = "The ID of a Coder agent." +} + +variable "vault_addr" { + type = string + description = "The address of the Vault server." +} + +variable "vault_token" { + type = string + description = "The Vault token to use for authentication." + sensitive = true +} + +variable "vault_cli_version" { + type = string + description = "The version of Vault to install." + default = "latest" + validation { + condition = can(regex("^(latest|[0-9]+\\.[0-9]+\\.[0-9]+)$", var.vault_cli_version)) + error_message = "Vault version must be in the format 0.0.0 or latest" + } +} + +data "coder_workspace" "me" {} + +resource "coder_script" "vault" { + agent_id = var.agent_id + display_name = "Vault (Token)" + icon = "/icon/vault.svg" + script = templatefile("${path.module}/run.sh", { + INSTALL_VERSION : var.vault_cli_version, + }) + run_on_start = true + start_blocks_login = true +} + +resource "coder_env" "vault_addr" { + agent_id = var.agent_id + name = "VAULT_ADDR" + value = var.vault_addr +} + +resource "coder_env" "vault_token" { + agent_id = var.agent_id + name = "VAULT_TOKEN" + value = var.vault_token +} diff --git a/vault-token/run.sh b/vault-token/run.sh new file mode 100644 index 0000000..cb5125d --- /dev/null +++ b/vault-token/run.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash + +# Convert all templated variables to shell variables +INSTALL_VERSION=${INSTALL_VERSION} + +fetch() { + dest="$1" + url="$2" + if command -v curl > /dev/null 2>&1; then + curl -sSL --fail "$${url}" -o "$${dest}" + elif command -v wget > /dev/null 2>&1; then + wget -O "$${dest}" "$${url}" + elif command -v busybox > /dev/null 2>&1; then + busybox wget -O "$${dest}" "$${url}" + else + printf "curl, wget, or busybox is not installed. Please install curl or wget in your image.\n" + return 1 + fi +} + +unzip_safe() { + if command -v unzip > /dev/null 2>&1; then + command unzip "$@" + elif command -v busybox > /dev/null 2>&1; then + busybox unzip "$@" + else + printf "unzip or busybox is not installed. Please install unzip in your image.\n" + return 1 + fi +} + +install() { + # Fetch the latest version of Vault if INSTALL_VERSION is 'latest' + if [ "$${INSTALL_VERSION}" = "latest" ]; then + LATEST_VERSION=$(curl -s https://releases.hashicorp.com/vault/ | grep -v '-rc' | grep -oP 'vault/\K[0-9]+\.[0-9]+\.[0-9]+' | sort -V | tail -n 1) + printf "Latest version of Vault is %s.\n\n" "$${LATEST_VERSION}" + if [ -z "$${LATEST_VERSION}" ]; then + printf "Failed to determine the latest Vault version.\n" + return 1 + fi + INSTALL_VERSION=$${LATEST_VERSION} + fi + + # Check if the vault CLI is installed and has the correct version + installation_needed=1 + if command -v vault > /dev/null 2>&1; then + CURRENT_VERSION=$(vault version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') + if [ "$${CURRENT_VERSION}" = "$${INSTALL_VERSION}" ]; then + printf "Vault version %s is already installed and up-to-date.\n\n" "$${CURRENT_VERSION}" + installation_needed=0 + fi + fi + + if [ $${installation_needed} -eq 1 ]; then + # Download and install Vault + if [ -z "$${CURRENT_VERSION}" ]; then + printf "Installing Vault CLI ...\n\n" + else + printf "Upgrading Vault CLI from version %s to %s ...\n\n" "$${CURRENT_VERSION}" "${INSTALL_VERSION}" + fi + fetch vault.zip "https://releases.hashicorp.com/vault/$${INSTALL_VERSION}/vault_$${INSTALL_VERSION}_linux_amd64.zip" + if [ $? -ne 0 ]; then + printf "Failed to download Vault.\n" + return 1 + fi + if ! unzip_safe vault.zip; then + printf "Failed to unzip Vault.\n" + return 1 + fi + rm vault.zip + if sudo mv vault /usr/local/bin/vault 2> /dev/null; then + printf "Vault installed successfully!\n\n" + else + mkdir -p ~/.local/bin + if ! mv vault ~/.local/bin/vault; then + printf "Failed to move Vault to local bin.\n" + return 1 + fi + printf "Please add ~/.local/bin to your PATH to use vault CLI.\n" + fi + fi + return 0 +} + +TMP=$(mktemp -d) +if ! ( + cd "$TMP" + install +); then + echo "Failed to install Vault CLI." + exit 1 +fi +rm -rf "$TMP" diff --git a/vscode-web/README.md b/vscode-web/README.md index 475968e..bc030d4 100644 --- a/vscode-web/README.md +++ b/vscode-web/README.md @@ -14,7 +14,7 @@ Automatically install [Visual Studio Code Server](https://code.visualstudio.com/ ```tf module "vscode-web" { source = "registry.coder.com/modules/vscode-web/coder" - version = "1.0.2" + version = "1.0.3" agent_id = coder_agent.example.id accept_license = true } @@ -29,7 +29,7 @@ module "vscode-web" { ```tf module "vscode-web" { source = "registry.coder.com/modules/vscode-web/coder" - version = "1.0.2" + version = "1.0.3" agent_id = coder_agent.example.id install_prefix = "/home/coder/.vscode-web" folder = "/home/coder"