Skip to content

Commit ec0c80b

Browse files
Merge remote-tracking branch 'origin/main'
2 parents 63a6c8b + 866ff3c commit ec0c80b

File tree

7 files changed

+95
-64
lines changed

7 files changed

+95
-64
lines changed

IAM_SSM_Setup.md

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ SageMaker SSH Helper relies on the AWS Systems Manager service to create SSH tun
1212

1313
### Automated setup with CDK and Cloud9
1414

15-
a. From AWS Console, pop up [CloudShell](https://aws.amazon.com/cloudshell/) environment. Alternatively, you can the commands run in your local terminal. In this case, make sure you've installed Node.js and CDK and fulfilled [all other CDK prerequisites](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_prerequisites). In both cases you need to have an admin role.
15+
a. From AWS Console, pop up [CloudShell](https://aws.amazon.com/cloudshell/) environment (use the button located at the bottom left corner of the browser window). Alternatively, you can the commands run in your local terminal. In this case, make sure you've installed Node.js and CDK and fulfilled [all other CDK prerequisites](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_prerequisites). In both cases you need to have an admin role.
1616

1717
b. Define your SageMaker role, local user role, AWS account ID and AWS Region as variables by executing the following commands in the terminal line by line:
1818

1919
```shell
2020
SAGEMAKER_ROLE_ARN=...
2121
USER_ROLE_ARN=...
22-
ACCOUNT_ID=
23-
REGION=
22+
ACCOUNT_ID=...
23+
REGION=...
2424
```
2525

2626
Note that if you connect to AWS from your local CLI as an IAM user, you will need to assume a `USER_ROLE_ARN` when connecting to SageMaker.
@@ -31,18 +31,19 @@ b. Execute the following commands (you can copy-paste them as a whole script):
3131

3232
```shell
3333
pip install 'sagemaker-ssh-helper[cdk]'
34+
npm install -g aws-cdk
3435

3536
cdk bootstrap aws://"$ACCOUNT_ID"/"$REGION"
3637

37-
APP="python -m sagemaker_ssh_helper.cdk.iam_ssm_app"
38+
IAM_APP="python -m sagemaker_ssh_helper.cdk.iam_ssm_app"
3839

39-
AWS_REGION="$REGION" cdk -a "$APP" deploy SSH-IAM-SSM-Stack \
40+
AWS_REGION="$REGION" cdk -a "$IAM_APP" deploy SSH-IAM-SSM-Stack \
4041
-c sagemaker_role="$SAGEMAKER_ROLE_ARN" \
4142
-c user_role="$USER_ROLE_ARN"
4243

43-
APP="python -m sagemaker_ssh_helper.cdk.advanced_tier_app"
44+
SSM_APP="python -m sagemaker_ssh_helper.cdk.advanced_tier_app"
4445

45-
AWS_REGION="$REGION" cdk -a "$APP" deploy SSM-Advanced-Tier-Stack
46+
AWS_REGION="$REGION" cdk -a "$SSM_APP" deploy SSM-Advanced-Tier-Stack
4647
```
4748

4849
In the above code we define local variable `APP` to execute CDK apps, and export `AWS_REGION` environment variable upon execution that is set to `REGION` local variable defined earlier.
@@ -52,16 +53,13 @@ Local variables `SAGEMAKER_ROLE_ARN` and `USER_ROLE_ARN` are passed as parameter
5253
c. To enable SageMaker SSH Helper in additional AWS Regions, run these commands per region (adjust `REGION` variable each time):
5354

5455
```shell
55-
ACCOUNT_ID=
56-
REGION=
56+
REGION=...
5757
```
5858

5959
```shell
6060
cdk bootstrap aws://"$ACCOUNT_ID"/"$REGION"
6161

62-
APP="python -m sagemaker_ssh_helper.cdk.advanced_tier_app"
63-
64-
AWS_REGION="$REGION" cdk -a "$APP" deploy SSM-Advanced-Tier-Stack
62+
AWS_REGION="$REGION" cdk -a "$SSM_APP" deploy SSM-Advanced-Tier-Stack
6563
```
6664

6765
*Note:* If you will run the jobs from SageMaker Studio instead of your local machine, specify `USER_ROLE_ARN` the same as `SAGEMAKER_ROLE_ARN`.

README.md

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ Install the latest stable version of library from the [PyPI repository](https://
9090
```shell
9191
pip install sagemaker-ssh-helper
9292
```
93+
9394
**Caution:** It's always recommended to install the library into a Python venv, not into the system env. If you want to use later the SSH plugins of your IDE that will use the system env and system Python, you should add the venv into the system PATH, as described in the section [Remote code execution with PyCharm / VSCode over SSH](#remote-interpreter).
9495

9596
If you're working on Windows, see [FAQ](FAQ.md#is-windows-supported).
@@ -583,6 +584,7 @@ Follow the steps in the next section for the IDE configuration, to prepare the `
583584
1. On the local machine, make sure that you installed the latest [AWS CLI v2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) and the [AWS Session Manager CLI plugin](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html). To do so, perform the automated installation with the [sm-local-configure](sagemaker_ssh_helper/sm-local-configure) script:
584585

585586
```shell
587+
# pip install sagemaker-ssh-helper
586588
sm-local-configure
587589
```
588590

@@ -752,21 +754,25 @@ If everything is set up correctly, PyCharm will stop at your breakpoint, highlig
752754

753755
## <a name="studio"></a>Local IDE integration with SageMaker Studio over SSH for PyCharm / VSCode
754756

755-
[![Download Demo (.mov)](https://user-images.githubusercontent.com/87804596/205895890-e5e87f8b-1ca6-4ce6-bac1-5cb6e6f61dde.png)](https://aws-blogs-artifacts-public.s3.amazonaws.com/artifacts/ML-4988/SSH_Helper-Remote-IDE.mov)
756-
[Download Demo (.mov)](https://aws-blogs-artifacts-public.s3.amazonaws.com/artifacts/ML-4988/SSH_Helper-Remote-IDE.mov)
757-
758-
> **Note**: This demo is recorded with a previous version of SSH Helper and may be not up-to-date with the recent features. Check the documentation for the most up-to-date steps.
757+
![SSH_Helper-Remote-IDE.png](https://user-images.githubusercontent.com/87804596/205895890-e5e87f8b-1ca6-4ce6-bac1-5cb6e6f61dde.png)
759758

760759
For your local IDE integration with SageMaker Studio, follow the same steps as for configuring the IDE for [Remote code execution](#remote-interpreter), but instead of submitting the training / processing / inference code to SageMaker with Python SDK, execute the Jupyter notebook, as described in the next steps.
761760

761+
> **Important:** Make sure you read the "Getting started" section and didn't skip the steps from [Setting up your AWS account with IAM and SSM configuration](IAM_SSM_Setup.md).
762+
763+
762764
1. Copy [SageMaker_SSH_IDE.ipynb](SageMaker_SSH_IDE.ipynb) into SageMaker Studio and run it.
763765

764766
Note that the `main` branch of this repo can contain changes that are not compatible with the version of `sagemaker-ssh-helper` that you installed from pip.
765767

766768
To be completely sure that you're using the version of the notebook that corresponds to the installed library, take a copy of the notebook from your filesystem after you install SSH Helper package, e.g.:
767769

768770
```bash
769-
cp /opt/conda/sm_ssh/SageMaker_SSH_IDE.ipynb /root/
771+
pip install sagemaker-ssh-helper
772+
SM_SSH_PREFIX=`python -c 'import sys; print(sys.prefix);'`
773+
echo $SM_SSH_PREFIX
774+
# check the output, e.g. /opt/conda
775+
cp $SM_SSH_PREFIX/sm_ssh/SageMaker_SSH_IDE.ipynb ~/user-default-efs/
770776
```
771777

772778
You can also check the version with `pip freeze | grep sagemaker-ssh-helper` and take the notebook from [the corresponding release tag](https://github.com/aws-samples/sagemaker-ssh-helper/tags).
@@ -780,7 +786,7 @@ You might want to change the `LOCAL_USER_ID` variable upon the first run, to pre
780786

781787
2. Configure remote interpreter in PyCharm / VS Code to connect to SageMaker Studio
782788

783-
Use `app_name.user_profile_name.domain_id.studio.sagemaker` or `app_name.studio.sagemaker` as the `fqdn` to connect.
789+
Use `app_name.app_space_name.domain_id.studio.sagemaker` or `app_name.studio.sagemaker` as the `fqdn` to connect.
784790

785791
To see available apps to connect to, you may run the `list` command:
786792

@@ -870,15 +876,15 @@ Instead of your local user ID put the SageMaker Studio user ID (you can get it b
870876
3. On the System (!) terminal (not image terminal), run:
871877

872878
```shell
873-
sm-ssh connect app_name.user_profile_name.domain_id.studio.sagemaker
879+
sm-ssh connect app_name.app_space_name.domain_id.studio.sagemaker
874880
```
875881

876882
Alternatively, use SSH command to forward the VNC port and add more ports to the command, e.g., `-L localhost:8787:localhost:8787` to forward the Dask dashboard that is running inside the kernel gateway:
877883

878884
```shell
879885
ssh -L localhost:5901:localhost:5901 \
880886
-L localhost:8787:localhost:8787 \
881-
app_name.user_profile_name.domain_id.studio.sagemaker
887+
app_name.app_space_name.domain_id.studio.sagemaker
882888
```
883889

884890
4. Navigate to `https://d-egm0dexample.studio.eu-west-1.sagemaker.aws/jupyter/default/proxy/6080/vnc.html?host=d-egm0dexample.studio.eu-west-1.sagemaker.aws&port=443&path=jupyter/default/proxy/6080/websockify`

SageMaker_SSH_IDE.ipynb

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,18 @@
7373
"outputs": [],
7474
"source": [
7575
"%%sh\n",
76-
"sm-ssh-ide configure\n",
77-
"#sm-ssh-ide configure --ssh-only"
76+
"cd /opt/"
77+
]
78+
},
79+
{
80+
"cell_type": "code",
81+
"execution_count": null,
82+
"metadata": {},
83+
"outputs": [],
84+
"source": [
85+
"%%sh\n",
86+
"#sm-ssh-ide configure\n",
87+
"sm-ssh-ide configure --ssh-only"
7888
]
7989
},
8090
{
@@ -110,7 +120,10 @@
110120
"cell_type": "code",
111121
"execution_count": null,
112122
"metadata": {
113-
"collapsed": false
123+
"collapsed": false,
124+
"jupyter": {
125+
"outputs_hidden": false
126+
}
114127
},
115128
"outputs": [],
116129
"source": [
@@ -213,8 +226,8 @@
213226
"outputs": [],
214227
"source": [
215228
"%%sh\n",
216-
"sm-ssh-ide stop\n",
217-
"sm-ssh-ide start"
229+
"sudo sm-ssh-ide stop\n",
230+
"sudo sm-ssh-ide start"
218231
]
219232
},
220233
{
@@ -231,7 +244,7 @@
231244
"outputs": [],
232245
"source": [
233246
"%%sh\n",
234-
"sm-ssh-ide ssm-agent"
247+
"sudo sm-ssh-ide ssm-agent"
235248
]
236249
},
237250
{
@@ -851,9 +864,9 @@
851864
],
852865
"instance_type": "ml.m5.large",
853866
"kernelspec": {
854-
"display_name": "Python 3 (Data Science 2.0)",
867+
"display_name": "Python 3 (ipykernel)",
855868
"language": "python",
856-
"name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:eu-west-1:470317259841:image/sagemaker-data-science-38"
869+
"name": "python3"
857870
},
858871
"language_info": {
859872
"codemirror_mode": {
@@ -865,7 +878,7 @@
865878
"name": "python",
866879
"nbconvert_exporter": "python",
867880
"pygments_lexer": "ipython3",
868-
"version": "3.8.13"
881+
"version": "3.11.11"
869882
}
870883
},
871884
"nbformat": 4,

sagemaker_ssh_helper/sm-helper-functions

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ function _silent_install() {
1616
install_path="/usr/local/bin"
1717

1818
dir=$(dirname "$0")
19+
dir=$(cd "$dir" && pwd)
1920
script=$1
2021
mod=$2
2122

@@ -27,6 +28,7 @@ function _silent_install() {
2728

2829
function _install_helper_scripts() {
2930
dir=$(dirname "$0")
31+
dir=$(cd "$dir" && pwd)
3032

3133
# Scripts may not be available in PATH during bootstrap, so we manually copy scripts into /usr/local/bin/.
3234
_silent_install sm-helper-functions
@@ -186,17 +188,22 @@ function _print_sm_app_name() {
186188
echo -n "$sm_resource_metadata_json" | sed -e 's/^.*"ResourceName":\"\([^"]*\)\".*$/\1/'
187189
}
188190

191+
# shellcheck disable=SC2001
192+
function _print_sm_execution_role() {
193+
sm_resource_metadata_json=$(tr -d "\n" < /opt/ml/metadata/resource-metadata.json)
194+
echo -n "$sm_resource_metadata_json" | sed -e 's/^.*"ExecutionRoleArn":\"\([^"]*\)\".*$/\1/'
195+
}
196+
189197
# shellcheck disable=SC2001
190198
function _print_sm_domain_id() {
191199
sm_resource_metadata_json=$(tr -d "\n" < /opt/ml/metadata/resource-metadata.json)
192200
echo -n "$sm_resource_metadata_json" | sed -e 's/^.*"DomainId":\"\([^"]*\)\".*$/\1/'
193201
}
194202

195203
# shellcheck disable=SC2001
196-
function _print_sm_user_profile_name() {
197-
# FIXME: Check for "SpaceName" - spaces are not supported yet
204+
function _print_sm_app_space_name() {
198205
sm_resource_metadata_json=$(tr -d "\n" < /opt/ml/metadata/resource-metadata.json)
199-
echo -n "$sm_resource_metadata_json" | sed -e 's/^.*"UserProfileName":\"\([^"]*\)\".*$/\1/'
206+
echo -n "$sm_resource_metadata_json" | sed -e 's/^.*"SpaceName":\"\([^"]*\)\".*$/\1/'
200207
}
201208

202209
function _print_sm_studio_python() {

sagemaker_ssh_helper/sm-init-ssm

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,9 @@ response=$(aws ssm create-activation \
5959
acode=$(echo $response | jq --raw-output '.ActivationCode')
6060
aid=$(echo $response | jq --raw-output '.ActivationId')
6161

62-
echo Yes | amazon-ssm-agent -register -id "$aid" -code "$acode" -region "$CURRENT_REGION"
62+
if [[ "$1" == "--sudo" ]]; then
63+
echo Yes | sudo amazon-ssm-agent -register -id "$aid" -code "$acode" -region "$CURRENT_REGION"
64+
else
65+
# Should be already root
66+
echo Yes | amazon-ssm-agent -register -id "$aid" -code "$acode" -region "$CURRENT_REGION"
67+
fi

sagemaker_ssh_helper/sm-setup-ssh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ if [[ "$1" == "configure" ]]; then
3636
exit 0
3737
fi
3838

39-
chmod 1777 /tmp
39+
chmod 1777 /tmp 2>/dev/null || echo "Cannot fix permissions of /tmp. Probably, already fixed and all is OK"
4040
mkdir -p ~/.ssh
4141
[ -d /usr/share/man/man1 ] || mkdir /usr/share/man/man1
4242

sagemaker_ssh_helper/sm-ssh-ide

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,41 @@ set -e
1414
set -o pipefail
1515

1616
dir=$(dirname "$0")
17+
dir=$(cd "$dir" && pwd)
1718
source "$dir"/sm-helper-functions
1819

19-
if [[ "$1" == "configure" ]]; then
20-
# Everything that requires root and Internet goes to 'configure'
21-
if [[ -f /opt/sagemaker-ssh-helper/.ssh-ide-configured ]]; then
22-
echo "sm-ssh-ide: Already configured. Remove /opt/sagemaker-ssh-helper/.ssh-ide-configured to force reconfiguration."
23-
exit 0
24-
fi
25-
26-
echo "sm-ssh-ide: Configuring services..."
27-
28-
OPTIONS=$2
29-
mkdir -p /opt/sagemaker-ssh-helper/
30-
echo "$OPTIONS" > /opt/sagemaker-ssh-helper/.sm-ssh-ide-options
31-
20+
if [[ "$1" == "install-helper-scripts" ]]; then
21+
echo "sm-ssh-ide: Installing helper scripts to /usr/local/bin/"
3222
_install_helper_scripts
23+
elif [[ "$1" == "configure" ]]; then
24+
# Everything that requires Internet goes to 'configure'
3325

34-
cat >/etc/profile.d/sm-ssh-ide.sh <<EOF
26+
sudo tee /etc/profile.d/sm-ssh-ide.sh >/dev/null <<EOF
27+
echo "Configuring SageMaker SSH Helper from /etc/profile.d/sm-ssh-ide.sh" >/dev/null
3528
export XAUTHORITY="/tmp/.Xauthority-\$USER"
3629
export ICEAUTHORITY="/tmp/.ICEauthority-\$USER"
3730
touch "/tmp/.Xauthority-\$USER"
3831
touch "/tmp/.ICEauthority-\$USER"
3932
chmod 600 "/tmp/.Xauthority-\$USER"
4033
chmod 600 "/tmp/.ICEauthority-\$USER"
4134
EOF
35+
4236
source /etc/profile.d/sm-ssh-ide.sh
4337

44-
sm-setup-ssh configure
38+
if [[ -f /opt/sagemaker-ssh-helper/.ssh-ide-configured ]]; then
39+
echo "sm-ssh-ide: Already configured. Remove /opt/sagemaker-ssh-helper/.ssh-ide-configured to force reconfiguration."
40+
exit 0
41+
fi
42+
43+
echo "sm-ssh-ide: Configuring services..."
44+
45+
OPTIONS=$2
46+
sudo mkdir -p /opt/sagemaker-ssh-helper/
47+
echo "$OPTIONS" | sudo tee /opt/sagemaker-ssh-helper/.sm-ssh-ide-options >/dev/null
48+
49+
sudo "$dir"/sm-ssh-ide install-helper-scripts
50+
51+
sudo sm-setup-ssh configure
4552

4653
if [[ "$OPTIONS" != "--ssh-only" ]]; then
4754

@@ -75,13 +82,13 @@ EOF
7582
echo "sm-ssh-ide: Skipping VNC and GUI apps install"
7683
fi
7784

78-
touch /opt/sagemaker-ssh-helper/.ssh-ide-configured
85+
sudo touch /opt/sagemaker-ssh-helper/.ssh-ide-configured
7986

8087
echo "sm-ssh-ide: Finished configuration. Done"
8188

82-
elif [[ "$1" == "get-user-profile-name" ]]; then
89+
elif [[ "$1" == "get-app-space-name" ]]; then
8390
_assert_is_ssh_ide_inside_studio
84-
USER_PROFILE=$(_print_sm_user_profile_name)
91+
USER_PROFILE=$(_print_sm_app_space_name)
8592
echo "$USER_PROFILE"
8693

8794
elif [[ "$1" == "get-domain-id" ]]; then
@@ -93,14 +100,14 @@ elif [[ "$1" == "get-metadata" ]]; then
93100
_assert_is_ssh_ide_inside_studio
94101

95102
echo "App name: $(_print_sm_app_name)"
96-
echo "User profile name: $(_print_sm_user_profile_name)"
103+
echo "App space name: $(_print_sm_app_space_name)"
97104
echo "Domain: $(_print_sm_domain_id)"
98105
echo ""
99106
echo "Connect from local machine: "
100107
echo "sm-ssh connect $(_print_sm_app_name).studio.sagemaker"
101-
echo "sm-ssh connect $(_print_sm_app_name).$(_print_sm_user_profile_name).$(_print_sm_domain_id).studio.sagemaker"
108+
echo "sm-ssh connect $(_print_sm_app_name).$(_print_sm_app_space_name).$(_print_sm_domain_id).studio.sagemaker"
102109
echo "ssh -A $(_print_sm_app_name).studio.sagemaker"
103-
echo "ssh -A $(_print_sm_app_name).$(_print_sm_user_profile_name).$(_print_sm_domain_id).studio.sagemaker"
110+
echo "ssh -A $(_print_sm_app_name).$(_print_sm_app_space_name).$(_print_sm_domain_id).studio.sagemaker"
104111

105112
elif [[ "$1" == "set-jb-license-server" ]]; then
106113

@@ -119,7 +126,7 @@ elif [[ "$1" == "set-jb-license-server" ]]; then
119126
echo "sm-ssh-ide: Skipping the update of /etc/hosts with PyCharm license server (already there)"
120127
else
121128
echo "sm-ssh-ide: Updating /etc/hosts with PyCharm license server from ~/.sm-jb-license-server"
122-
echo "127.0.0.1 $JB_LICENSE_SERVER_HOST" >> /etc/hosts
129+
echo "127.0.0.1 $JB_LICENSE_SERVER_HOST" | sudo tee -a /etc/hosts
123130
fi
124131

125132
elif [[ "$1" == "set-vnc-password" ]]; then
@@ -159,13 +166,8 @@ elif [[ "$1" == "init-ssm" ]]; then
159166
LOCAL_USER_ID="$(cat ~/.sm-ssh-owner)"
160167
echo "sm-ssh-ide: Will use local user ID: $LOCAL_USER_ID"
161168

162-
user_profile_json=$(aws sagemaker describe-user-profile \
163-
--domain-id "$(_print_sm_domain_id)" \
164-
--user-profile-name "$(_print_sm_user_profile_name)" \
165-
--output json \
166-
| tr -d "\n")
167-
execution_role=$(echo "$user_profile_json" | { grep "ExecutionRole" || true; } \
168-
| sed -e 's/^.*"ExecutionRole": \"\([^"]*\)\".*$/\1/')
169+
execution_role=$(_print_sm_execution_role)
170+
echo "sm-ssh-ide: Detected SageMaker execution role ARN: $execution_role"
169171

170172
SSH_SSM_ROLE=$(echo "$execution_role" | sed -e 's/^.*:role\/\(.*\)/\1/')
171173

@@ -188,7 +190,7 @@ elif [[ "$1" == "init-ssm" ]]; then
188190
export SSH_SSM_ROLE
189191
export SSH_OWNER_TAG=$LOCAL_USER_ID
190192

191-
sm-init-ssm
193+
sm-init-ssm --sudo
192194

193195
echo "sm-ssh-ide: SSM initialized. Done"
194196

0 commit comments

Comments
 (0)