Update sshd-debian.sh to restore environment variables for login shells (#871)

This commit is contained in:
Chuck Lantz 2021-06-03 19:14:10 -07:00 коммит произвёл GitHub
Родитель 2904e1c519
Коммит 6646e6cb9f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
16 изменённых файлов: 293 добавлений и 48 удалений

10
.github/workflows/script-library.yml поставляемый
Просмотреть файл

@ -13,7 +13,7 @@ jobs:
if: "!contains(github.event.head_commit.message, 'Automated update') && !contains(github.event.head_commit.message, 'CI ignore')"
strategy:
matrix:
os: [debian, alpine, redhat]
os: [debian, ubuntu, alpine, centos]
fail-fast: false
runs-on: ubuntu-latest
steps:
@ -34,13 +34,7 @@ jobs:
id: test_script_library
run: |
set -e
cd script-library
if [ "${{ matrix.os }}" = "redhat" ]; then
IMAGE_TO_TEST="centos:7"
else
IMAGE_TO_TEST=${{ matrix.os }}
fi
docker build --build-arg DISTRO=${{ matrix.os }} --build-arg IMAGE_TO_TEST=$IMAGE_TO_TEST -f test/Dockerfile .
bash script-library/test/regression/test.sh "${{ matrix.os }}"
copy-scripts:
name: Copy and commit script-library updates

Просмотреть файл

@ -141,7 +141,7 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
## Testing
The `test` sub-folder includes Debian, Alpine, and RedHat based dev containers that can be used to test the scripts.
The `test/regression` sub-folder includes Debian, Alpine, and RedHat based dev containers that can be used to test the scripts.
## Contributing

Просмотреть файл

@ -11,7 +11,7 @@
## Syntax
```text
./sshd-debian.sh [SSH Port] [Non-root user] [Start SSHD now flag] [New password for user]
./sshd-debian.sh [SSH Port] [Non-root user] [Start SSHD now flag] [New password for user] [Fix environment flag]
```
|Argument|Default|Description|
@ -20,6 +20,7 @@
| Non-root user |`automatic`| Specifies a user in the container other than root that will use SSH. A value of `automatic` will cause the script to check for a user called `vscode`, then `node`, `codespace`, and finally a user with a UID of `1000` before falling back to `root`. |
|Start SSHD now flag |`false`| Flag (`true`/`false`) that specifies whether the SSH server should be started after the script runs.|
|New password for user|`skip`| Sets a new password for the specified non-root user. A value of `skip` will skip this step. A value of `random` will generate a random password and print it out when the script finishes. |
|Fix environment flag|`true`|Connections using the SSH daemon use "fresh" login shells that will not contain any environment or `PATH` updates made in the image. By default the script will wire into login shell creation, add any environment variables not already set, and base the `PATH` off of what was set in the Dockerifle. Set to false if you experience unexpected problems. |
## Usage
@ -45,7 +46,7 @@ Usage:
3. Your container/codespace now has a running SSH server in it. Use a **local terminal** (or other tool) to connect to it using the command and password from step 2. e.g.
```bash
ssh -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null codespace@localhost
ssh -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o GlobalKnownHostsFile=/dev/null codespace@localhost
```
...where `codespace` above is the user you are running as in the container (e.g. `codespace`, `vscode`, `node`, or `root`) and `2222` after `-p` is the **local address port** from step 2.
@ -94,7 +95,7 @@ Usage:
5. Connect to the container or [codespace using VS Code](https://docs.github.com/en/github/developing-online-with-codespaces/connecting-to-your-codespace-from-visual-studio-code). You can now SSH into the container on port `2222`. For example, if you are in the container as the `vscode` user, run the following command in a **local terminal**:
```bash
ssh -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null vscode@localhost
ssh -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o GlobalKnownHostsFile=/dev/null vscode@localhost
```
...where `vscode` above is the user you are running as in the container (e.g. `codespace`, `vscode`, `node`, or `root`).
@ -140,7 +141,7 @@ If you already have a running container, you can use the script to spin up SSH i
[SSHFS](https://en.wikipedia.org/wiki/SSHFS) allows you to mount a remote filesystem to your local machine with nothing but a SSH connection. Here's how to use it with a dev container.
1. Follow the steps in one of the previous sections to ensure you can connect to the dev contaienr using the normal `ssh` client.
1. Follow the steps in one of the previous sections to ensure you can connect to the dev container using the normal `ssh` client.
2. Install a SSHFS client.
@ -154,7 +155,7 @@ If you already have a running container, you can use the script to spin up SSH i
```
mkdir -p ~/sshfs/devcontainer
sshfs "vscode@localhost:/workspaces" "$HOME/sshfs/devcontainer" -p 2222 -o follow_symlinks -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -C
sshfs "vscode@localhost:/workspaces" "$HOME/sshfs/devcontainer" -p 2222 -o follow_symlinks -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o GlobalKnownHostsFile=/dev/null -C
```
...where `vscode` above is the user you are running as in the container (e.g. `codespace`, `vscode`, `node`, or `root`) and `2222` after the `-p` is the same local port you used in the `ssh` command in step 1.

Просмотреть файл

@ -7,7 +7,7 @@
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/sshd.md
# Maintainer: The VS Code and Codespaces Teams
#
# Syntax: ./sshd-debian.sh [SSH Port (don't use 22)] [non-root user] [start sshd now flag] [new password for user]
# Syntax: ./sshd-debian.sh [SSH Port (don't use 22)] [non-root user] [start sshd now flag] [new password for user] [fix environment flag]
#
# Note: You can change your user's password with "sudo passwd $(whoami)" (or just "passwd" if running as root).
@ -15,6 +15,7 @@ SSHD_PORT=${1:-"2222"}
USERNAME=${2:-"automatic"}
START_SSHD=${3:-"false"}
NEW_PASSWORD=${4:-"skip"}
FIX_ENVIRONMENT=${5:-"true"}
set -e
@ -23,12 +24,6 @@ if [ "$(id -u)" -ne 0 ]; then
exit 1
fi
# SSH uses a login shells, so we need to ensure these get the same initial PATH as non-login shells.
# /etc/profile wipes out the path which is a problem when the PATH was modified using the ENV directive in a Dockerfile.
rm -f /etc/profile.d/00-restore-env.sh
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
chmod +x /etc/profile.d/00-restore-env.sh
# Determine the appropriate non-root user
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
@ -61,57 +56,103 @@ apt-get-update-if-needed()
export DEBIAN_FRONTEND=noninteractive
# Install openssh-server openssh-client
if ! dpkg -s openssh-server openssh-client > /dev/null 2>&1; then
if ! dpkg -s openssh-server openssh-client lsof jq > /dev/null 2>&1; then
apt-get-update-if-needed
apt-get -y install --no-install-recommends openssh-server openssh-client
apt-get -y install --no-install-recommends openssh-server openssh-client lsof jq
fi
# Generate password if new password set to the word "random"
if [ "${NEW_PASSWORD}" = "random" ]; then
NEW_PASSWORD="$(openssl rand -hex 16)"
EMIT_PASSWORD="true"
elif [ "${NEW_PASSWORD}" != "skip" ]; then
# If new password not set to skip, set it for the specified user
echo "${USERNAME}:${NEW_PASSWORD}" | chpasswd
fi
# If new password not set to skip, set it for the specified user
if [ "${NEW_PASSWORD}" != "skip" ]; then
echo "${USERNAME}:${NEW_PASSWORD}" | chpasswd
if [ "${NEW_PASSWORD}" != "root" ]; then
usermod -aG ssh ${USERNAME}
fi
# Add user to ssh group
if [ "${USERNAME}" != "root" ]; then
usermod -aG ssh ${USERNAME}
fi
# Setup sshd
mkdir -p /var/run/sshd
sed -i 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' /etc/pam.d/sshd
sed -i 's/session\s*required\s*pam_loginuid\.so/session optional pam_loginuid.so/g' /etc/pam.d/sshd
sed -i 's/#*PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config
sed -i -E "s/#*\s*Port\s+.+/Port ${SSHD_PORT}/g" /etc/ssh/sshd_config
# Need to UsePAM so /etc/environment is processed
sed -i -E "s/#?\s*UsePAM\s+.+/UsePAM yes/g" /etc/ssh/sshd_config
# Write out a script that can be referenced as an ENTRYPOINT to auto-start sshd
# Script to store variables that exist at the time the ENTRYPOINT is fired
STORE_ENV_SCRIPT="$(cat << 'EOF'
# Wire in codespaces secret processing to zsh if present (since may have been added to image after script was run)
if [ -f /etc/zsh/zlogin ] && ! grep '/etc/profile.d/00-restore-secrets.sh' /etc/zsh/zlogin > /dev/null 2>&1; then
echo -e "if [ -f /etc/profile.d/00-restore-secrets.sh ]; then . /etc/profile.d/00-restore-secrets.sh; fi\n$(cat /etc/zsh/zlogin 2>/dev/null || echo '')" | sudoIf tee /etc/zsh/zlogin > /dev/null
fi
EOF
)"
# Script to ensure login shells get the latest Codespaces secrets
RESTORE_SECRETS_SCRIPT="$(cat << 'EOF'
#!/bin/sh
if [ "${CODESPACES}" != "true" ] || [ "${VSCDC_FIXED_SECRETS}" = "true" ] || [ ! -z "${GITHUB_CODESPACES_TOKEN}" ]; then
# Not codespaces, already run, or secrets already in environment, so return
return
fi
if [ -f /workspaces/.codespaces/shared/.user-secrets.json ]; then
$(cat /workspaces/.codespaces/shared/.user-secrets.json | jq -r '.[] | select (.type=="EnvironmentVariable") | "export "+.name+"=\""+.value+"\""')
fi
export VSCDC_FIXED_SECRETS=true
EOF
)"
# Write out a scripts that can be referenced as an ENTRYPOINT to auto-start sshd and fix login environments
tee /usr/local/share/ssh-init.sh > /dev/null \
<< EOF
<< 'EOF'
#!/usr/bin/env bash
# This script is intended to be run as root with a container that runs as root (even if you connect with a different user)
# However, it supports running as a user other than root if passwordless sudo is configured for that same user.
set -e
if [ "\$(id -u)" -ne 0 ]; then
sudo /etc/init.d/ssh start > /tmp/sshd.log 2>&1
else
/etc/init.d/ssh start > /tmp/sshd.log 2>&1
sudoIf()
{
if [ "$(id -u)" -ne 0 ]; then
sudo "$@"
else
"$@"
fi
}
EOF
if [ "${FIX_ENVIRONMENT}" = "true" ]; then
echo "${STORE_ENV_SCRIPT}" >> /usr/local/share/ssh-init.sh
echo "${RESTORE_SECRETS_SCRIPT}" > /etc/profile.d/00-restore-secrets.sh
chmod +x /etc/profile.d/00-restore-secrets.sh
# Wire in zsh if present
if type zsh > /dev/null 2>&1; then
echo -e "if [ -f /etc/profile.d/00-restore-secrets.sh ]; then . /etc/profile.d/00-restore-secrets.sh; fi\n$(cat /etc/zsh/zlogin 2>/dev/null || echo '')" > /etc/zsh/zlogin
fi
fi
tee -a /usr/local/share/ssh-init.sh > /dev/null \
<< 'EOF'
# ** Start SSH server **
sudoIf /etc/init.d/ssh start 2>&1 | sudoIf tee /tmp/sshd.log > /dev/null
set +e
exec "\$@"
exec "$@"
EOF
chmod +x /usr/local/share/ssh-init.sh
chown ${USERNAME}:ssh /usr/local/share/ssh-init.sh
# If we should start sshd now, do so
if [ "${START_SSHD}" = "true" ]; then
/usr/local/share/ssh-init.sh
fi
# Write out result
# Output success details
echo -e "Done!\n\n- Port: ${SSHD_PORT}\n- User: ${USERNAME}"
if [ "${EMIT_PASSWORD}" = "true" ]; then
echo "- Password: ${NEW_PASSWORD}"
fi
echo -e "\nForward port ${SSHD_PORT} to your local machine and run:\n\n ssh -p ${SSHD_PORT} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${USERNAME}@localhost\n"
echo -e "\nForward port ${SSHD_PORT} to your local machine and run:\n\n ssh -p ${SSHD_PORT} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o GlobalKnownHostsFile=/dev/null ${USERNAME}@localhost\n"

Просмотреть файл

@ -8,7 +8,7 @@ ARG IMAGE_TO_TEST=debian:10
FROM ${IMAGE_TO_TEST}
COPY *.sh /tmp/
COPY test/*.sh /tmp
COPY test/regression/*.sh /tmp/
RUN chmod +x /tmp/*.sh
ARG DISTRO="debian"

Просмотреть файл

@ -2,15 +2,14 @@
"name": "Script Tester - Alpine",
"build": {
"dockerfile": "../Dockerfile",
"context": "../../",
"context": "../../../",
"args": {
"IMAGE_TO_TEST": "alpine",
"USERNAME": "vscode",
"DISTRO": "alpine"
}
},
"workspaceMount": "source=${localWorkspaceFolder}/../..,target=/workspace,type=bind",
"workspaceMount": "source=${localWorkspaceFolder}/../../..,target=/workspace,type=bind",
"workspaceFolder": "/workspace",
"remoteUser": "vscode"

Просмотреть файл

@ -2,7 +2,7 @@
"name": "Script Tester - Debian",
"build": {
"dockerfile": "../Dockerfile",
"context": "../../",
"context": "../../../",
"args": {
"IMAGE_TO_TEST": "debian",
"DISTRO": "debian",
@ -13,7 +13,7 @@
}
},
"remoteUser": "vscode",
"workspaceMount": "source=${localWorkspaceFolder}/../..,target=/workspace,type=bind",
"workspaceMount": "source=${localWorkspaceFolder}/../../..,target=/workspace,type=bind",
"workspaceFolder": "/workspace",
"mounts": [ "source=/var/run/docker.sock,target=/var/run/docker-host.sock,type=bind" ],
"runArgs": ["--init", "--security-opt", "seccomp=unconfined"],

Просмотреть файл

@ -2,7 +2,7 @@
"name": "Script Tester - RedHat",
"build": {
"dockerfile": "../Dockerfile",
"context": "../../",
"context": "../../../",
"args": {
"IMAGE_TO_TEST": "centos:7",
"USERNAME": "vscode",
@ -11,7 +11,7 @@
},
"mounts": [ "source=/var/run/docker.sock,target=/var/run/docker-host.sock,type=bind" ],
"workspaceMount": "source=${localWorkspaceFolder}/../..,target=/workspace,type=bind",
"workspaceMount": "source=${localWorkspaceFolder}/../../..,target=/workspace,type=bind",
"workspaceFolder": "/workspace",
"overrideCommand": false,

Просмотреть файл

@ -0,0 +1,17 @@
#!/usr/bin/env bash
IMAGE_TO_TEST="${1:-debian}"
if [ "$IMAGE_TO_TEST" = "centos" ]; then
DISTRO="redhat"
elif [ "${IMAGE_TO_TEST}" = "ubuntu" ]; then
DISTRO="debian"
else
DISTRO=$IMAGE_TO_TEST
fi
set -e
cd "$(cd "$(dirname "$0")" && pwd)/../.."
echo -e "🧪 Testing image $IMAGE_TO_TEST (${DISTRO}-like)..."
docker build --build-arg DISTRO=$DISTRO --build-arg IMAGE_TO_TEST=$IMAGE_TO_TEST -f test/regression/Dockerfile .
echo -e "\n🎉 All tests passed!"

Просмотреть файл

@ -0,0 +1,20 @@
ARG IMAGE_TO_TEST="mcr.microsoft.com/vscode/devcontainers/base:0-focal"
FROM $IMAGE_TO_TEST
ENV PATH=/front-dockerfile-pre-script:$PATH:/back-dockerfile-pre-script
ENV this_var=true
ARG DEFAULT_SHELL_TYPE=bash
COPY sshd-debian.sh test/sshd/*.sh /tmp/scripts/
ARG current_user=$USER
USER root
RUN apt-get update \
&& bash /tmp/scripts/sshd-debian.sh \
&& bash /tmp/scripts/test-prep.sh ${DEFAULT_SHELL_TYPE}
USER $current_user
ENV that_var=true
ENV PATH=/front-dockerfile-post-script:$PATH:/back-dockerfile-post-script
ENTRYPOINT [ "/usr/local/share/ssh-init.sh" ]
CMD [ "sleep", "infinity" ]

Просмотреть файл

@ -0,0 +1,18 @@
{
"name": "Test SSHD script",
"build": {
"dockerfile": "../Dockerfile",
"context": "../../../",
"args": {
"IMAGE_TO_TEST": "mcr.microsoft.com/vscode/devcontainers/base:0-buster",
"DEFAULT_SHELL_TYPE": "bash"
}
},
"remoteUser": "vscode",
"userEnvProbe": "none",
"overrideCommand": false,
"forwardPorts": [2222],
"workspaceMount": "source=${localWorkspaceFolder}/../../..,target=/workspace,type=bind",
"workspaceFolder": "/workspace"
}

Просмотреть файл

@ -0,0 +1,71 @@
#!/usr/bin/env bash
USERNAME=${1:-$(whoami)}
RUN_CODESPACES_TESTS=${2:-false}
set -e
# Work around wierdness with $HOME in images where this is set by something else
if [ "${USERNAME}" = "root" ]; then
HOME="/root"
fi
if [ ! -f $HOME/.ssh/test.id_rsa ]; then
mkdir -p $HOME/.ssh
chmod 700 $HOME/.ssh
yes | ssh-keygen -q -b 2048 -t rsa -N '' -C "$USERNAME@localhost" -f $HOME/.ssh/test.id_rsa
cat $HOME/.ssh/test.id_rsa.pub >> $HOME/.ssh/authorized_keys
chmod 644 $HOME/.ssh/authorized_keys
fi
check_result() {
local shell_to_test=$1
local teset_result=$2
local regex=$3
if echo "$test_result" | grep -E "$regex" > /dev/null 2>&1; then
echo " ✔️ $regex passed."
return 0
fi
echo "$regex failed!"
return 1
}
run_test() {
# Processing is async, so sleep for 1s
sleep 1s
local shell_to_test=$1
local test_result="$(ssh -q -p 2222 -i $HOME/.ssh/test.id_rsa -o StrictHostKeyChecking=no -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null $USERNAME@localhost $shell_to_test -lic 'env' 2> /dev/null)"
echo -e "\n🧪 Run \"${USERNAME}\" user tests for $1...\n(*) Environment for $shell_to_test:\n$test_result"
echo "(*) /etc/environment contents:"
cat /etc/environment
echo "(*) Running environment var tests for $1..."
check_result "$shell_to_test" "$test_result" 'this_var="?true"?'
check_result "$shell_to_test" "$test_result" 'that_var="?true"?'
if [ "${RUN_CODESPACES_TESTS}" = "true" ]; then
check_result "$shell_to_test" "$test_result" 'CODESPACES="?true"?'
check_result "$shell_to_test" "$test_result" "GITHUB_TOKEN=.*"
check_result "$shell_to_test" "$test_result" "GITHUB_CODESPACE_TOKEN=.*"
check_result "$shell_to_test" "$test_result" "GIT_COMMITTER_NAME=.*"
check_result "$shell_to_test" "$test_result" "GIT_COMMITTER_EMAIL=.*"
fi
echo "(*) Running PATH tests for $1..."
check_result "$shell_to_test" "$test_result" "PATH=.*/front-dockerfile-pre-script:.*:/back-dockerfile-pre-script.*"
check_result "$shell_to_test" "$test_result" "PATH=.*/front-dockerfile-post-script:.*:/back-dockerfile-post-script.*"
check_result "$shell_to_test" "$test_result" "PATH=.*(/front-profile-post-export:|/front-profile-begin:).*(:/back-profile-post-export|:/back-profile-begin).*"
if [ "$shell_to_test" != "zsh" ]; then
check_result "$shell_to_test" "$test_result" "PATH=.*/front-profile-pre-rc:.*:/back-profile-pre-rc.*"
check_result "$shell_to_test" "$test_result" "PATH=.*/front-pre-profile\.d:.*:/back-pre-profile\.d.*"
fi
check_result "$shell_to_test" "$test_result" "PATH=.*/front-profile-end:.*:/back-profile-end.*"
if [ "$shell_to_test" != "sh" ]; then
check_result "$shell_to_test" "$test_result" "PATH=.*/front-rc:.*"
check_result "$shell_to_test" "$test_result" "PATH=.*:/back-rc.*"
fi
echo "👍 All $1 tests passed for user \"$USERNAME\". "
}
run_test bash
if type zsh > /dev/null 2>&1; then
run_test zsh
fi
run_test sh
echo -e "\n🏆 All shell tests passed for user \"$USERNAME\"!"

Просмотреть файл

@ -0,0 +1,18 @@
#!/usr/bin/env bash
RUN_CODESPACES_TESTS=${1:-false}
cd "$(cd "$(dirname "$0")" && pwd)"
set -e
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
./test-in-container-for-user.sh root $RUN_CODESPACES_TESTS
USERNAME="$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd 2>/dev/null)"
if [ "${USERNAME}" != "" ]; then
su $USERNAME -c ./test-in-container-for-user.sh $USERNAME $RUN_CODESPACES_TESTS
fi
echo -e "\n🙌 Tests passed for all users!"

Просмотреть файл

@ -0,0 +1,24 @@
#!/usr/bin/env bash
DEFAULT_SHELL_TYPE=$1
set -e
apt-get update
apt-get -y install zsh
echo -e "export PATH=/front-profile-begin:\$PATH:/back-profile-begin\n$(cat /etc/profile)" > /etc/profile
echo -e "export PATH=/front-profile-begin:\$PATH:/back-profile-begin\n$(cat /etc/zsh/zlogin)" > /etc/zsh/zlogin
sed -i 's%export PATH$%&\nexport PATH=/front-profile-post-export:$PATH:/back-profile-post-export%g' /etc/profile
sed -i 's%if \[ "\${PS1-}" \]; then%export PATH=/front-profile-pre-rc:$PATH:/back-profile-pre-rc\n&%g' /etc/profile
sed -i 's%if \[ -d /etc/profile\.d \]; then%export PATH=/front-pre-profile.d:$PATH:/back-pre-profile.d\n&%g' /etc/profile
echo "export PATH=/front-profile-end:\$PATH:/back-profile-end" | tee -a /etc/zsh/zlogin >> /etc/profile
echo "export PATH=/front-rc:\$PATH:/back-rc" | tee -a /etc/zsh/zshrc >> /etc/bash.bashrc
echo "etc_env_var=true" >> /etc/environment
echo -e "vscode\nvscode" | passwd root 2>&1
USERNAME="$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd 2>/dev/null)"
if [ "${USERNAME}" != "" ]; then
chown $USERNAME /usr/local/share/ssh-init.sh
echo -e "vscode\nvscode" | passwd $USERNAME 2>&1
chsh -s $(which $DEFAULT_SHELL_TYPE) $USERNAME
fi

Просмотреть файл

@ -0,0 +1,42 @@
[
{
"type": "EnvironmentVariable",
"name": "GITHUB_TOKEN",
"value": "foo"
},
{
"type": "EnvironmentVariable",
"name": "GITHUB_CODESPACE_TOKEN",
"value": "foo"
},
{
"type": "EnvironmentVariable",
"name": "GIT_COMMITTER_NAME",
"value": "foo"
},
{
"type": "EnvironmentVariable",
"name": "GIT_COMMITTER_EMAIL",
"value": "foo@foo.com"
},
{
"type": "ContainerRegistry",
"name": "docker.pkg.github.com",
"value": "foo"
},
{
"type": "EnvironmentVariable",
"name": "GH_TOKEN",
"value": "foo"
},
{
"type": "EnvironmentVariable",
"name": "GH_USER",
"value": "foo"
},
{
"type": "ContainerRegistry",
"name": "foo@https://index.docker.io/v1/",
"value": "foo@https://index.docker.io/v1/"
}
]