From f7f28c777a40a637b8532720414e3508dcb167be Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Wed, 24 Jan 2024 03:48:05 +0300 Subject: [PATCH 01/17] Update jfrog.md --- docs/platforms/jfrog.md | 241 ++++++---------------------------------- 1 file changed, 31 insertions(+), 210 deletions(-) diff --git a/docs/platforms/jfrog.md b/docs/platforms/jfrog.md index 5ed569632c962..48cdb9a4ea7c5 100644 --- a/docs/platforms/jfrog.md +++ b/docs/platforms/jfrog.md @@ -13,8 +13,7 @@ The full example template can be found ## Requirements - A JFrog Artifactory instance -- An admin-level access token for Artifactory -- 1:1 mapping of users in Coder to users in Artifactory by email address and +- 1:1 mapping of users in Coder to users in Artifactory by email address or username - Repositories configured in Artifactory for each package manager you want to use @@ -31,230 +30,52 @@ You can skip the whole page and use [JFrog module](https://registry.coder.com/mo ## Provisioner Authentication The most straight-forward way to authenticate your template with Artifactory is -by using -[Terraform-managed variables](https://coder.com/docs/v2/latest/templates/parameters#terraform-template-wide-variables). +by using our officaial Coder [modules](rhttps://egistry.coder.com). We publish two type of modules that automate the JFrog Artifactory and Coder integartion. -See the following example: +1. JFrog-OAuth: +2. JFrog-Token: -```hcl -terraform { - required_providers { - coder = { - source = "coder/coder" - } - docker = { - source = "kreuzwerker/docker" - } - artifactory = { - source = "registry.terraform.io/jfrog/artifactory" - } - } -} - -variable "jfrog_url" { - type = string - description = "JFrog instance URL. e.g. https://jfrog.example.com" - # validate the URL to ensure it starts with https:// or http:// - validation { - condition = can(regex("^https?://", var.jfrog_url)) - error_message = "JFrog URL must start with https:// or http://" - } -} - -variable "artifactory_admin_access_token" { - type = string - description = "The admin-level access token to use for JFrog with scope applied-permissions/admin" -} - -# Configure the Artifactory provider -provider "artifactory" { - url = "${var.jfrog_url}/artifactory" - access_token = "${var.artifactory_admin_access_token}" -} - -resource "artifactory_scoped_token" "me" { - # This is hacky, but on terraform plan the data source gives empty strings, - # which fails validation. - username = length(local.artifactory_username) > 0 ? local.artifactory_username : "plan" -} -``` - -When pushing the template, you can pass in the variables using the `--var` flag: +### JFrog-OAuth -```shell -coder templates push --var 'jfrog_url=https://YYY.jfrog.io' --var 'artifactory_admin_access_token=XXX' -``` - -## Installing JFrog CLI - -`jf` is the JFrog CLI. It can do many things across the JFrog platform, but -we'll focus on its ability to configure package managers, as that's the relevant -functionality for most developers. - -Most users should be able to install `jf` by running the following command: - -```shell -curl -fL https://install-cli.jfrog.io | sh -``` - -Other methods are listed [here](https://jfrog.com/getcli/). - -In our Docker-based example, we install `jf` by adding these lines to our -`Dockerfile`: - -```Dockerfile -RUN curl -fL https://install-cli.jfrog.io | sh && chmod 755 $(which jf) -``` - -## Configuring Coder workspace to use JFrog Artifactory repositories - -Create a `locals` block to store the Artifactory repository keys for each -package manager you want to use in your workspace. For example, if you want to -use artifactory repositories with keys `npm`, `pypi`, and `go`, you can create a -`locals` block like this: +This module is usable by Jfrog self-hossted(on-premises) Artifactory as it requires configuring a custom integration. This integration benefits from Coder's [external-auth](https://coder.com/docs/v2/latest/admin/external-auth) feature and allows each user to authticate with Artifactory using an OAuth flow and issues user-scoped tokens to each user. For instrutions on how to set this up, please see the details at: https://registry.coder.com/modules/jfrog-oauth ```hcl -locals { - artifactory_repository_keys = { - npm = "npm" - python = "pypi" - go = "go" +module "jfrog" { + source = "registry.coder.com/modules/jfrog-oauth/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + jfrog_url = "https://jfrog.example.com" + username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username" + package_managers = { + "npm": "npm", + "go": "go", + "pypi": "pypi" } - # Make sure to use the same field as the username field in the Artifactory - # It can be either the username or the email address. - artifactory_username = data.coder_workspace.me.owner_email - jfrog_host = replace(var.jfrog_url, "^https://", "") } ``` -To automatically configure `jf` CLI and Artifactory repositories for each user, -add the following lines to your `startup_script` in the `coder_agent` block: - -```hcl -resource "coder_agent" "main" { - arch = data.coder_provisioner.me.arch - os = "linux" - startup_script_timeout = 180 - startup_script = <<-EOT - set -e - - # install and start code-server - curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server - /tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 & - - # The jf CLI checks $CI when determining whether to use interactive - # flows. - export CI=true - - jf c rm 0 || true - echo ${artifactory_scoped_token.me.access_token} | \ - jf c add --access-token-stdin --url ${var.jfrog_url} 0 - - # Configure the `npm` CLI to use the Artifactory "npm" repository. - cat << EOF > ~/.npmrc - email = ${data.coder_workspace.me.owner_email} - registry = ${var.jfrog_url}/artifactory/api/npm/${local.artifactory_repository_keys["npm"]} - EOF - jf rt curl /api/npm/auth >> .npmrc +### JFrog-Token - # Configure the `pip` to use the Artifactory "python" repository. - mkdir -p ~/.pip - cat << EOF > ~/.pip/pip.conf - [global] - index-url = https://${local.artifactory_username}:${artifactory_scoped_token.me.access_token}@${local.jfrog_host}/artifactory/api/pypi/${local.artifactory_repository_keys["python"]}/simple - EOF +This module makes use of the [Artifactory terraform provider](https://registry.terraform.io/providers/jfrog/artifactory/latest/docs) and an admin-scoped token to create user-scoped tokens for each user by matching their Coder email or username with Artifactory. This can be used for both SaaS and self-hosted(on-premisis) Artifactory instances. For Instrctions on how to configure this, please see the details at: https://registry.coder.com/modules/jfrog-token - EOT - # Set GOPROXY to use the Artifactory "go" repository. - env = { - GOPROXY : "https://${local.artifactory_username}:${artifactory_scoped_token.me.access_token}@${local..jfrog_host}/artifactory/api/go/${local.artifactory_repository_keys["go"]}" +```hcl +module "jfrog" { + source = "registry.coder.com/modules/jfrog-token/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + jfrog_url = "https://XXXX.jfrog.io" + artifactory_access_token = var.artifactory_access_token + package_managers = { + "npm": "npm", + "go": "go", + "pypi": "pypi" } } ``` -You can verify that `jf` is configured correctly in your workspace by running -`jf c show`. It should display output like: - -```text -coder@jf:~$ jf c show -Server ID: 0 -JFrog Platform URL: https://YYY.jfrog.io/ -Artifactory URL: https://YYY.jfrog.io/artifactory/ -Distribution URL: https://YYY.jfrog.io/distribution/ -Xray URL: https://YYY.jfrog.io/xray/ -Mission Control URL: https://YYY.jfrog.io/mc/ -Pipelines URL: https://YYY.jfrog.io/pipelines/ -User: ammar@....com -Access token: ... -Default: true -``` - -## Installing the JFrog VS Code Extension - -You can install the JFrog VS Code extension into workspaces by inserting the -following lines into your `startup_script`: - -```shell -# Install the JFrog VS Code extension. -# Find the latest version number at -# https://open-vsx.org/extension/JFrog/jfrog-vscode-extension. -/tmp/code-server/bin/code-server --install-extension jfrog.jfrog-vscode-extension -``` - -Note that this method will only work if your developers use code-server. - -## Configuring npm - -Add the following line to your `startup_script` to configure `npm` to use -Artifactory: - -```shell - # Configure the `npm` CLI to use the Artifactory "npm" registry. - cat << EOF > ~/.npmrc - email = ${data.coder_workspace.me.owner_email} - registry = ${var.jfrog_url}/artifactory/api/npm/npm/ - EOF - jf rt curl /api/npm/auth >> .npmrc -``` - -Now, your developers can run `npm install`, `npm audit`, etc. and transparently -use Artifactory as the package registry. You can verify that `npm` is configured -correctly by running `npm install --loglevel=http react` and checking that npm -is only hitting your Artifactory URL. - -## Configuring pip - -Add the following lines to your `startup_script` to configure `pip` to use -Artifactory: - -```shell - mkdir -p ~/.pip - cat << EOF > ~/.pip/pip.conf - [global] - index-url = https://${data.coder_workspace.me.owner}:${artifactory_scoped_token.me.access_token}@${local.jfrog_host}/artifactory/api/pypi/pypi/simple - EOF -``` - -Now, your developers can run `pip install` and transparently use Artifactory as -the package registry. You can verify that `pip` is configured correctly by -running `pip install --verbose requests` and checking that pip is only hitting -your Artifactory URL. - -## Configuring Go - -Add the following environment variable to your `coder_agent` block to configure -`go` to use Artifactory: - -```hcl - env = { - GOPROXY : "https://${data.coder_workspace.me.owner}:${artifactory_scoped_token.me.access_token}@${local.jfrog_host}/artifactory/api/go/go" - } -``` +## Offline Deployments -You can apply the same concepts to Docker, Maven, and other package managers -supported by Artifactory. See the -[JFrog documentation](https://jfrog.com/help/r/jfrog-artifactory-documentation/package-management) -for more information. +TODO ## More reading From 5a7e7b8c0dbe92f12ccfdbbe499e4889bf0f7acf Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Wed, 24 Jan 2024 01:08:55 +0000 Subject: [PATCH 02/17] formatting and typos --- docs/platforms/jfrog.md | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/docs/platforms/jfrog.md b/docs/platforms/jfrog.md index 48cdb9a4ea7c5..46b8571c32907 100644 --- a/docs/platforms/jfrog.md +++ b/docs/platforms/jfrog.md @@ -18,26 +18,24 @@ The full example template can be found - Repositories configured in Artifactory for each package manager you want to use -
-The admin-level access token is used to provision user tokens and is never exposed to -developers or stored in workspaces. -
- -
-You can skip the whole page and use [JFrog module](https://registry.coder.com/modules/jfrog-token) for easy JFrog Artifactory integration. -
- ## Provisioner Authentication The most straight-forward way to authenticate your template with Artifactory is -by using our officaial Coder [modules](rhttps://egistry.coder.com). We publish two type of modules that automate the JFrog Artifactory and Coder integartion. +by using our official Coder [modules](rhttps://egistry.coder.com). We publish +two type of modules that automate the JFrog Artifactory and Coder integration. -1. JFrog-OAuth: -2. JFrog-Token: +1. JFrog-OAuth: +2. JFrog-Token: ### JFrog-OAuth -This module is usable by Jfrog self-hossted(on-premises) Artifactory as it requires configuring a custom integration. This integration benefits from Coder's [external-auth](https://coder.com/docs/v2/latest/admin/external-auth) feature and allows each user to authticate with Artifactory using an OAuth flow and issues user-scoped tokens to each user. For instrutions on how to set this up, please see the details at: https://registry.coder.com/modules/jfrog-oauth +This module is usable by Jfrog self-hosted (on-premises) Artifactory as it +requires configuring a custom integration. This integration benefits from +Coder's [external-auth](https://coder.com/docs/v2/latest/admin/external-auth) +feature and allows each user to authenticate with Artifactory using an OAuth +flow and issues user-scoped tokens to each user. For instructions on how to set +this up, please see the details at: +https://registry.coder.com/modules/jfrog-oauth ```hcl module "jfrog" { @@ -56,7 +54,13 @@ module "jfrog" { ### JFrog-Token -This module makes use of the [Artifactory terraform provider](https://registry.terraform.io/providers/jfrog/artifactory/latest/docs) and an admin-scoped token to create user-scoped tokens for each user by matching their Coder email or username with Artifactory. This can be used for both SaaS and self-hosted(on-premisis) Artifactory instances. For Instrctions on how to configure this, please see the details at: https://registry.coder.com/modules/jfrog-token +This module makes use of the +[Artifactory terraform provider](https://registry.terraform.io/providers/jfrog/artifactory/latest/docs) +and an admin-scoped token to create user-scoped tokens for each user by matching +their Coder email or username with Artifactory. This can be used for both SaaS +and self-hosted(on-premises) Artifactory instances. For Instructions on how to +configure this, please see the details at: +https://registry.coder.com/modules/jfrog-token ```hcl module "jfrog" { @@ -73,9 +77,16 @@ module "jfrog" { } ``` +
+The admin-level access token is used to provision user tokens and is never exposed to +developers or stored in workspaces. +
+ ## Offline Deployments -TODO +See the [offline deployments](../install/offline.md#coder-modules) guide for +instructions on how to use coder-modules in an offline environment with +Artifactory. ## More reading From 4bd4ff0051b7cece5f0ec5d03d5469c40d0ad762 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Wed, 24 Jan 2024 01:15:08 +0000 Subject: [PATCH 03/17] move to guides --- docs/{platforms => guides}/jfrog.md | 14 +++++++++++++- docs/manifest.json | 5 ----- 2 files changed, 13 insertions(+), 6 deletions(-) rename docs/{platforms => guides}/jfrog.md (90%) diff --git a/docs/platforms/jfrog.md b/docs/guides/jfrog.md similarity index 90% rename from docs/platforms/jfrog.md rename to docs/guides/jfrog.md index 46b8571c32907..8ec2884982b45 100644 --- a/docs/platforms/jfrog.md +++ b/docs/guides/jfrog.md @@ -1,3 +1,15 @@ +# Coder JFrog Integration + +
+ + Your Name + + +
+January 24, 20204 + +--- + # JFrog Use Coder and JFrog together to secure your development environments without @@ -84,7 +96,7 @@ developers or stored in workspaces. ## Offline Deployments -See the [offline deployments](../install/offline.md#coder-modules) guide for +See the [offline deployments](../install/offline.md#coder-modules) section for instructions on how to use coder-modules in an offline environment with Artifactory. diff --git a/docs/manifest.json b/docs/manifest.json index e863e27572f10..0d2aba2188688 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -88,11 +88,6 @@ "path": "./platforms/gcp.md", "icon_path": "./images/google-cloud.svg" }, - { - "title": "JFrog", - "description": "Integrate Coder with JFrog", - "path": "./platforms/jfrog.md" - }, { "title": "Kubernetes", "description": "Set up Coder on Kubernetes", From 4a86f6d10dac131cab73bde52c56f0a8504f5233 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Wed, 24 Jan 2024 11:44:51 +0300 Subject: [PATCH 04/17] review comments --- docs/guides/jfrog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guides/jfrog.md b/docs/guides/jfrog.md index 8ec2884982b45..6c26265d26438 100644 --- a/docs/guides/jfrog.md +++ b/docs/guides/jfrog.md @@ -33,7 +33,7 @@ The full example template can be found ## Provisioner Authentication The most straight-forward way to authenticate your template with Artifactory is -by using our official Coder [modules](rhttps://egistry.coder.com). We publish +by using our official Coder [modules](https://registry.coder.com). We publish two type of modules that automate the JFrog Artifactory and Coder integration. 1. JFrog-OAuth: @@ -41,7 +41,7 @@ two type of modules that automate the JFrog Artifactory and Coder integration. ### JFrog-OAuth -This module is usable by Jfrog self-hosted (on-premises) Artifactory as it +This module is usable by JFrog self-hosted (on-premises) Artifactory as it requires configuring a custom integration. This integration benefits from Coder's [external-auth](https://coder.com/docs/v2/latest/admin/external-auth) feature and allows each user to authenticate with Artifactory using an OAuth From b2d99a9c88674795a6b7fe63e7a9ec279741e7c5 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Wed, 24 Jan 2024 12:03:40 +0300 Subject: [PATCH 05/17] Update jfrog.md --- docs/guides/jfrog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/jfrog.md b/docs/guides/jfrog.md index 6c26265d26438..0b160347ff520 100644 --- a/docs/guides/jfrog.md +++ b/docs/guides/jfrog.md @@ -2,7 +2,7 @@ From 80d94a965df88b013d0165723ebf731e76a4af6d Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Wed, 24 Jan 2024 12:19:00 +0300 Subject: [PATCH 06/17] add configure-code-server --- docs/guides/jfrog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/guides/jfrog.md b/docs/guides/jfrog.md index 0b160347ff520..51790d641c743 100644 --- a/docs/guides/jfrog.md +++ b/docs/guides/jfrog.md @@ -55,6 +55,7 @@ module "jfrog" { version = "1.0.0" agent_id = coder_agent.example.id jfrog_url = "https://jfrog.example.com" + configure_code_server = true # this depends on the code-server username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username" package_managers = { "npm": "npm", @@ -80,6 +81,7 @@ module "jfrog" { version = "1.0.0" agent_id = coder_agent.example.id jfrog_url = "https://XXXX.jfrog.io" + configure_code_server = true # this depends on the code-server artifactory_access_token = var.artifactory_access_token package_managers = { "npm": "npm", From 0745274725bbe6ccdabc85baaa1ec171a706dd22 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 26 Jan 2024 01:49:36 +0300 Subject: [PATCH 07/17] add manifest and rename --- docs/guides/{jfrog.md => coder-artifactory-integration.md} | 0 docs/manifest.json | 5 +++++ 2 files changed, 5 insertions(+) rename docs/guides/{jfrog.md => coder-artifactory-integration.md} (100%) diff --git a/docs/guides/jfrog.md b/docs/guides/coder-artifactory-integration.md similarity index 100% rename from docs/guides/jfrog.md rename to docs/guides/coder-artifactory-integration.md diff --git a/docs/manifest.json b/docs/manifest.json index 0d2aba2188688..4986de4485086 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1016,6 +1016,11 @@ "path": "./guides/index.md", "icon_path": "./images/icons/notes.svg", "children": [ + { + "title": "Coder JFrog Artifactory Integration", + "description": "Integrate Coder with JFrog Artifactory", + "path": "./guides/coder-artifactory-integration.md" + }, { "title": "Configuring Okta", "description": "Custom claims/scopes with Okta for group/role sync", From c36c574d368ae74527c44806ac17179d4b8903a2 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 26 Jan 2024 01:51:59 +0300 Subject: [PATCH 08/17] update --- docs/guides/coder-artifactory-integration.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/guides/coder-artifactory-integration.md b/docs/guides/coder-artifactory-integration.md index 51790d641c743..c7bbf7b126c2c 100644 --- a/docs/guides/coder-artifactory-integration.md +++ b/docs/guides/coder-artifactory-integration.md @@ -10,9 +10,7 @@ January 24, 20204 --- -# JFrog - -Use Coder and JFrog together to secure your development environments without +Use Coder and JFrog Artifactory together to secure your development environments without disturbing your developers' existing workflows. This guide will demonstrate how to use JFrog Artifactory as a package registry From 7b32f44515eec93b5ce0c52014b7160b7f5aab42 Mon Sep 17 00:00:00 2001 From: matifali Date: Thu, 25 Jan 2024 22:53:13 +0000 Subject: [PATCH 09/17] `fmt` --- docs/guides/coder-artifactory-integration.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guides/coder-artifactory-integration.md b/docs/guides/coder-artifactory-integration.md index c7bbf7b126c2c..f3e3fe463b408 100644 --- a/docs/guides/coder-artifactory-integration.md +++ b/docs/guides/coder-artifactory-integration.md @@ -10,8 +10,8 @@ January 24, 20204 --- -Use Coder and JFrog Artifactory together to secure your development environments without -disturbing your developers' existing workflows. +Use Coder and JFrog Artifactory together to secure your development environments +without disturbing your developers' existing workflows. This guide will demonstrate how to use JFrog Artifactory as a package registry within a workspace. We'll use Docker as the underlying compute. But, these From 03b3fd29be459fa596146a8df5909231648b43c0 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 26 Jan 2024 01:55:41 +0300 Subject: [PATCH 10/17] rename --- ...er-artifactory-integration.md => artifactory-integration.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename docs/guides/{coder-artifactory-integration.md => artifactory-integration.md} (99%) diff --git a/docs/guides/coder-artifactory-integration.md b/docs/guides/artifactory-integration.md similarity index 99% rename from docs/guides/coder-artifactory-integration.md rename to docs/guides/artifactory-integration.md index f3e3fe463b408..aec6c56ed1d70 100644 --- a/docs/guides/coder-artifactory-integration.md +++ b/docs/guides/artifactory-integration.md @@ -1,4 +1,4 @@ -# Coder JFrog Integration +# JFrog Artifactory Integration
From 3fe589631200a8e56f06f61609ed950b4730c9e8 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 26 Jan 2024 01:56:18 +0300 Subject: [PATCH 11/17] reorganize --- docs/manifest.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/manifest.json b/docs/manifest.json index 4986de4485086..898439121df46 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1016,11 +1016,6 @@ "path": "./guides/index.md", "icon_path": "./images/icons/notes.svg", "children": [ - { - "title": "Coder JFrog Artifactory Integration", - "description": "Integrate Coder with JFrog Artifactory", - "path": "./guides/coder-artifactory-integration.md" - }, { "title": "Configuring Okta", "description": "Custom claims/scopes with Okta for group/role sync", @@ -1031,6 +1026,11 @@ "description": "Federating a Google Cloud service account to AWS", "path": "./guides/gcp-to-aws.md" }, + { + "title": "JFrog Artifactory Integration", + "description": "Integrate Coder with JFrog Artifactory", + "path": "./guides/coder-artifactory-integration.md" + }, { "title": "Template ImagePullSecrets", "description": "Creating ImagePullSecrets for private registries", From b77b494095b27773014533fcaa6e384fe0cfba1b Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 26 Jan 2024 01:59:08 +0300 Subject: [PATCH 12/17] fixup! --- docs/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/manifest.json b/docs/manifest.json index 898439121df46..6ced6f0a1f8b6 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1029,7 +1029,7 @@ { "title": "JFrog Artifactory Integration", "description": "Integrate Coder with JFrog Artifactory", - "path": "./guides/coder-artifactory-integration.md" + "path": "./guides/artifactory-integration.md" }, { "title": "Template ImagePullSecrets", From 94f8b6f9524e1d717fb050cfed56ad3c2657ff07 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 26 Jan 2024 02:22:36 +0300 Subject: [PATCH 13/17] refactor --- docs/guides/artifactory-integration.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/guides/artifactory-integration.md b/docs/guides/artifactory-integration.md index aec6c56ed1d70..25bbfc47f97c8 100644 --- a/docs/guides/artifactory-integration.md +++ b/docs/guides/artifactory-integration.md @@ -14,11 +14,7 @@ Use Coder and JFrog Artifactory together to secure your development environments without disturbing your developers' existing workflows. This guide will demonstrate how to use JFrog Artifactory as a package registry -within a workspace. We'll use Docker as the underlying compute. But, these -concepts apply to any compute platform. - -The full example template can be found -[here](https://github.com/coder/coder/tree/main/examples/jfrog/docker). +within a workspace. ## Requirements @@ -94,6 +90,9 @@ The admin-level access token is used to provision user tokens and is never expos developers or stored in workspaces. +The full example template uses Docker as the underlying compute. But, these +concepts apply to any compute platform. Please check [here](https://github.com/coder/coder/tree/main/examples/jfrog/docker). + ## Offline Deployments See the [offline deployments](../install/offline.md#coder-modules) section for From bc1672e8dfb9543761f5dd74e80f89c76076e252 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 26 Jan 2024 02:54:13 +0300 Subject: [PATCH 14/17] Update JFrog integration instructions --- docs/guides/artifactory-integration.md | 55 ++++++++++++++++-- .../jfrog-oauth-app.png | Bin 0 -> 49383 bytes 2 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 docs/images/guides/artifactory-integration/jfrog-oauth-app.png diff --git a/docs/guides/artifactory-integration.md b/docs/guides/artifactory-integration.md index 25bbfc47f97c8..4ddb4a39dfe0e 100644 --- a/docs/guides/artifactory-integration.md +++ b/docs/guides/artifactory-integration.md @@ -30,8 +30,8 @@ The most straight-forward way to authenticate your template with Artifactory is by using our official Coder [modules](https://registry.coder.com). We publish two type of modules that automate the JFrog Artifactory and Coder integration. -1. JFrog-OAuth: -2. JFrog-Token: +1. JFrog-OAuth +2. JFrog-Token ### JFrog-OAuth @@ -39,9 +39,54 @@ This module is usable by JFrog self-hosted (on-premises) Artifactory as it requires configuring a custom integration. This integration benefits from Coder's [external-auth](https://coder.com/docs/v2/latest/admin/external-auth) feature and allows each user to authenticate with Artifactory using an OAuth -flow and issues user-scoped tokens to each user. For instructions on how to set -this up, please see the details at: -https://registry.coder.com/modules/jfrog-oauth +flow and issues user-scoped tokens to each user. + +To set this up, follow these steps: + +1. Modify your Helm chart `values.yaml` for JFrog Artifactory to add, + +```yaml +artifactory: + enabled: true + frontend: + extraEnvironmentVariables: + - name: JF_FRONTEND_FEATURETOGGLER_ACCESSINTEGRATION + value: "true" + access: + accessConfig: + integrations-enabled: true + integration-templates: + - id: "1" + name: "CODER" + redirect-uri: "https://CODER_URL/external-auth/jfrog/callback" + scope: "applied-permissions/user" +``` + +> Note +> Replace `CODER_URL` with your Coder deployment URL, e.g., + +2. Create a new Application Integration by going to and select the Application Type as the integration you created in step 1. + +![JFrog Platform new integration](../images/guides/artifactory-integration/jfrog-oauth-app.png) + +3. Add a new [external authentication](https://coder.com/docs/v2/latest/admin/external-auth) to Coder by setting these env variables, + +```env +# JFrog Artifactory External Auth +CODER_EXTERNAL_AUTH_1_ID="jfrog" +CODER_EXTERNAL_AUTH_1_TYPE="jfrog" +CODER_EXTERNAL_AUTH_1_CLIENT_ID="YYYYYYYYYYYYYYY" +CODER_EXTERNAL_AUTH_1_CLIENT_SECRET="XXXXXXXXXXXXXXXXXXX" +CODER_EXTERNAL_AUTH_1_DISPLAY_NAME="JFrog Artifactory" +CODER_EXTERNAL_AUTH_1_DISPLAY_ICON="/icon/jfrog.svg" +CODER_EXTERNAL_AUTH_1_AUTH_URL="https://JFROG_URL/ui/authorization" +CODER_EXTERNAL_AUTH_1_SCOPES="applied-permissions/user" +``` + +> Note +> Replace `JFROG_URL` with your JFrog Artifactory base URL, e.g., + +4. Create or edit a Coder template and use the [JFrog-OAuth](https://registry.coder.com/modules/jfrog-oauth) module to configure the integration. ```hcl module "jfrog" { diff --git a/docs/images/guides/artifactory-integration/jfrog-oauth-app.png b/docs/images/guides/artifactory-integration/jfrog-oauth-app.png new file mode 100644 index 0000000000000000000000000000000000000000..058fdf858ba9ca965958d6fb1bea8e90cbf7d79d GIT binary patch literal 49383 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 H83z0hniTSE literal 0 HcmV?d00001 From 5c7ef15e0cbe00a0654c1d382b09e3050c541208 Mon Sep 17 00:00:00 2001 From: matifali Date: Thu, 25 Jan 2024 23:58:17 +0000 Subject: [PATCH 15/17] fmt --- docs/guides/artifactory-integration.md | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/docs/guides/artifactory-integration.md b/docs/guides/artifactory-integration.md index 4ddb4a39dfe0e..29abf7e9a5bb4 100644 --- a/docs/guides/artifactory-integration.md +++ b/docs/guides/artifactory-integration.md @@ -62,14 +62,18 @@ artifactory: scope: "applied-permissions/user" ``` -> Note -> Replace `CODER_URL` with your Coder deployment URL, e.g., +> Note Replace `CODER_URL` with your Coder deployment URL, e.g., +> -2. Create a new Application Integration by going to and select the Application Type as the integration you created in step 1. +2. Create a new Application Integration by going to + and select the + Application Type as the integration you created in step 1. ![JFrog Platform new integration](../images/guides/artifactory-integration/jfrog-oauth-app.png) -3. Add a new [external authentication](https://coder.com/docs/v2/latest/admin/external-auth) to Coder by setting these env variables, +3. Add a new + [external authentication](https://coder.com/docs/v2/latest/admin/external-auth) + to Coder by setting these env variables, ```env # JFrog Artifactory External Auth @@ -83,10 +87,12 @@ CODER_EXTERNAL_AUTH_1_AUTH_URL="https://JFROG_URL/ui/authorization" CODER_EXTERNAL_AUTH_1_SCOPES="applied-permissions/user" ``` -> Note -> Replace `JFROG_URL` with your JFrog Artifactory base URL, e.g., +> Note Replace `JFROG_URL` with your JFrog Artifactory base URL, e.g., +> -4. Create or edit a Coder template and use the [JFrog-OAuth](https://registry.coder.com/modules/jfrog-oauth) module to configure the integration. +4. Create or edit a Coder template and use the + [JFrog-OAuth](https://registry.coder.com/modules/jfrog-oauth) module to + configure the integration. ```hcl module "jfrog" { @@ -136,7 +142,8 @@ developers or stored in workspaces. The full example template uses Docker as the underlying compute. But, these -concepts apply to any compute platform. Please check [here](https://github.com/coder/coder/tree/main/examples/jfrog/docker). +concepts apply to any compute platform. Please check +[here](https://github.com/coder/coder/tree/main/examples/jfrog/docker). ## Offline Deployments From 2e143d9f0836e5c4dcce42ee5e99ee374bb1f684 Mon Sep 17 00:00:00 2001 From: Muhammad Atif Ali Date: Fri, 26 Jan 2024 03:09:28 +0300 Subject: [PATCH 16/17] Update Artifactory integration instructions --- docs/guides/artifactory-integration.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/guides/artifactory-integration.md b/docs/guides/artifactory-integration.md index 29abf7e9a5bb4..ef9069eec696f 100644 --- a/docs/guides/artifactory-integration.md +++ b/docs/guides/artifactory-integration.md @@ -116,16 +116,24 @@ This module makes use of the [Artifactory terraform provider](https://registry.terraform.io/providers/jfrog/artifactory/latest/docs) and an admin-scoped token to create user-scoped tokens for each user by matching their Coder email or username with Artifactory. This can be used for both SaaS -and self-hosted(on-premises) Artifactory instances. For Instructions on how to -configure this, please see the details at: -https://registry.coder.com/modules/jfrog-token +and self-hosted(on-premises) Artifactory instances. + +To set this up, follow these steps: + +1. Get a JFrog access token from your Artifactory instance. The token must be an [admin token](https://registry.terraform.io/providers/jfrog/artifactory/latest/docs#access-token) with scope `applied-permissions/admin`. +2. Create or edit a Coder template and use the [JFrog-Token](https://registry.coder.com/modules/jfrog-token) module to configure the integration and pass the admin token. It is recommended to store the token in a sensitive terraform variable to prevent it from being displayed in plain text in the terraform state. ```hcl +variable "artifactory_access_token" { + type = string + sensitive = true +} + module "jfrog" { source = "registry.coder.com/modules/jfrog-token/coder" version = "1.0.0" agent_id = coder_agent.example.id - jfrog_url = "https://XXXX.jfrog.io" + jfrog_url = "https://example.jfrog.io" configure_code_server = true # this depends on the code-server artifactory_access_token = var.artifactory_access_token package_managers = { @@ -141,9 +149,7 @@ The admin-level access token is used to provision user tokens and is never expos developers or stored in workspaces. -The full example template uses Docker as the underlying compute. But, these -concepts apply to any compute platform. Please check -[here](https://github.com/coder/coder/tree/main/examples/jfrog/docker). +If you do not want to use the official modules, you can check example template that uses Docker as the underlying compute [here](https://github.com/coder/coder/tree/main/examples/jfrog/docker). The same concepts apply to all compute types. ## Offline Deployments From 3b5bc0a0a92b5b255c3092acce22cda5f30cfdf5 Mon Sep 17 00:00:00 2001 From: matifali Date: Fri, 26 Jan 2024 00:21:24 +0000 Subject: [PATCH 17/17] fmt --- docs/guides/artifactory-integration.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/guides/artifactory-integration.md b/docs/guides/artifactory-integration.md index ef9069eec696f..62bc84b952371 100644 --- a/docs/guides/artifactory-integration.md +++ b/docs/guides/artifactory-integration.md @@ -120,8 +120,14 @@ and self-hosted(on-premises) Artifactory instances. To set this up, follow these steps: -1. Get a JFrog access token from your Artifactory instance. The token must be an [admin token](https://registry.terraform.io/providers/jfrog/artifactory/latest/docs#access-token) with scope `applied-permissions/admin`. -2. Create or edit a Coder template and use the [JFrog-Token](https://registry.coder.com/modules/jfrog-token) module to configure the integration and pass the admin token. It is recommended to store the token in a sensitive terraform variable to prevent it from being displayed in plain text in the terraform state. +1. Get a JFrog access token from your Artifactory instance. The token must be an + [admin token](https://registry.terraform.io/providers/jfrog/artifactory/latest/docs#access-token) + with scope `applied-permissions/admin`. +2. Create or edit a Coder template and use the + [JFrog-Token](https://registry.coder.com/modules/jfrog-token) module to + configure the integration and pass the admin token. It is recommended to + store the token in a sensitive terraform variable to prevent it from being + displayed in plain text in the terraform state. ```hcl variable "artifactory_access_token" { @@ -149,7 +155,10 @@ The admin-level access token is used to provision user tokens and is never expos developers or stored in workspaces. -If you do not want to use the official modules, you can check example template that uses Docker as the underlying compute [here](https://github.com/coder/coder/tree/main/examples/jfrog/docker). The same concepts apply to all compute types. +If you do not want to use the official modules, you can check example template +that uses Docker as the underlying compute +[here](https://github.com/coder/coder/tree/main/examples/jfrog/docker). The same +concepts apply to all compute types. ## Offline Deployments