Closed tunguyen9889 closed 1 month ago
Hi @tunguyen9889 I am fighting with Teleport discovery service with fips binaries and I noticed that you created new installer named linux-installer-fips. Right now even after 2 modifications my SSM run cannot deploy teleport fips binaries. Teleport support said that it is a bug. Could you please give some hints how you implemented fips installation?
@ogorbachov what I have done is creating a new installer
script called linux-installer-fips
as following:
---
version: v1
kind: installer
metadata:
name: linux-installer-fips
spec:
script: |
#!/usr/bin/env bash
# shellcheck disable=SC1083,SC2215,SC2288 # caused by Go templating, and shellcheck won't parse if the lines are excluded individually
set -eu
upgrade_endpoint="{{ .PublicProxyAddr }}/v1/webapi/automaticupgrades/channel/default"
# upgrade_endpoint_fetch loads the specified value from the upgrade endpoint. the only
# currently supported values are 'version' and 'critical'.
upgrade_endpoint_fetch() {
host_path="${upgrade_endpoint}/${1}"
if sf_output="$(curl --proto '=https' --tlsv1.2 -sSf "https://${host_path}")"; then
# emit output with empty lines and extra whitespace removed
echo "$sf_output" | grep -v -e '^[[:space:]]*$' | awk '{$1=$1};1'
return 0
else
return 1
fi
}
# get_target_version loads the current value of the /version endpoint.
get_target_version() {
if tv_output="$(upgrade_endpoint_fetch version)"; then
# emit version string with leading 'v' removed if one is present
echo "${tv_output#v}"
return 0
fi
return 1
}
on_ec2() {
IMDS_TOKEN=$(curl -m5 -sS -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 300")
[ -z "$IMDS_TOKEN" ] && return 1
EC2_STATUS=$(curl -o /dev/null -w "%{http_code}" -m5 -sS -H "X-aws-ec2-metadata-token: ${IMDS_TOKEN}" "http://169.254.169.254/latest/meta-data")
[ "$EC2_STATUS" = "200" ]
}
on_azure() {
AZURE_STATUS=$(curl -o /dev/null -w "%{http_code}" -m5 -sS -H "Metadata: true" --noproxy "*" "http://169.254.169.254/metadata/instance?api-version=2021-02-01")
[ "$AZURE_STATUS" = "200" ]
}
on_gcp() {
GCP_STATUS=$(curl -o /dev/null -w "%{http_code}" -m5 -sS -H "Metadata-Flavor: Google" "http://metadata.google.internal/")
[ "$GCP_STATUS" = "200" ]
}
(
flock -n 9 || exit 1
if test -f /usr/local/bin/teleport; then
exit 0
fi
# shellcheck disable=SC1091
. /etc/os-release
TELEPORT_PACKAGE="{{ .TeleportPackage }}-fips"
TELEPORT_UPDATER_PACKAGE="{{ .TeleportPackage }}-updater"
if [ "$ID" = "debian" ] || [ "$ID" = "ubuntu" ]; then
# old versions of ubuntu require that keys get added by `apt-key add`, without
# adding the key apt shows a key signing error when installing teleport.
if [ "$VERSION_CODENAME" = "xenial" ] || [ "$VERSION_CODENAME" = "trusty" ]; then
curl -o /tmp/teleport-pubkey.asc https://apt.releases.teleport.dev/gpg
sudo apt-key add /tmp/teleport-pubkey.asc
echo "deb https://apt.releases.teleport.dev/ubuntu ${VERSION_CODENAME?} {{ .RepoChannel }}" | sudo tee /etc/apt/sources.list.d/teleport.list
rm /tmp/teleport-pubkey.asc
else
sudo curl https://apt.releases.teleport.dev/gpg \
-o /usr/share/keyrings/teleport-archive-keyring.asc
echo "deb [signed-by=/usr/share/keyrings/teleport-archive-keyring.asc] https://apt.releases.teleport.dev/${ID?} ${VERSION_CODENAME?} {{ .RepoChannel }}" | sudo tee /etc/apt/sources.list.d/teleport.list >/dev/null
fi
sudo apt-get update
# shellcheck disable=SC2050
if [ "{{ .AutomaticUpgrades }}" = "true" ]; then
# automatic upgrades
if ! target_version="$(get_target_version)"; then
# error getting the target version
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "$TELEPORT_PACKAGE" jq "$TELEPORT_UPDATER_PACKAGE"
elif [ "$target_version" == "none" ]; then
# no target version advertised
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "$TELEPORT_PACKAGE" jq "$TELEPORT_UPDATER_PACKAGE"
else
# successfully retrieved target version
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "$TELEPORT_PACKAGE=$target_version" jq "$TELEPORT_UPDATER_PACKAGE=$target_version"
fi
else
# no automatic upgrades
sudo apt-get install -y "$TELEPORT_PACKAGE" jq
fi
elif [ "$ID" = "amzn" ] || [ "$ID" = "rhel" ]; then
if [ "$ID" = "rhel" ]; then
VERSION_ID=${VERSION_ID//\.*/} # convert version numbers like '7.2' to only include the major version
fi
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo \
"$(rpm --eval "https://yum.releases.teleport.dev/$ID/$VERSION_ID/Teleport/%{_arch}/{{ .RepoChannel }}/teleport.repo")"
# shellcheck disable=SC2050
if [ "{{ .AutomaticUpgrades }}" = "true" ]; then
# automatic upgrades
if ! target_version="$(get_target_version)"; then
# error getting the target version
sudo yum install -y "$TELEPORT_PACKAGE" jq "$TELEPORT_UPDATER_PACKAGE"
elif [ "$target_version" == "none" ]; then
# no target version advertised
sudo yum install -y "$TELEPORT_PACKAGE" jq "$TELEPORT_UPDATER_PACKAGE"
else
# successfully retrieved target version
sudo yum install -y "$TELEPORT_PACKAGE-$target_version" jq "$TELEPORT_UPDATER_PACKAGE-$target_version"
fi
else
# no automatic upgrades
sudo yum install -y "$TELEPORT_PACKAGE" jq
fi
elif [ "$ID" = "sles" ] || [ "$ID" = "opensuse-tumbleweed" ] || [ "$ID" = "opensuse-leap" ]; then
if [ "$ID" = "opensuse-tumbleweed" ]; then
VERSION_ID="15" # tumbleweed uses dated VERSION_IDs like 20230702
else
VERSION_ID="${VERSION_ID//.*/}" # convert version numbers like '7.2' to only include the major version
fi
sudo rpm --import "https://zypper.releases.teleport.dev/gpg"
sudo zypper --non-interactive addrepo "$(rpm --eval "https://zypper.releases.teleport.dev/sles/$VERSION_ID/Teleport/%{_arch}/{{ .RepoChannel }}/teleport.repo")"
sudo zypper --gpg-auto-import-keys refresh
# shellcheck disable=SC2050
if [ "{{ .AutomaticUpgrades }}" = "true" ]; then
# automatic upgrades
if ! target_version="$(get_target_version)"; then
# error getting the target version
sudo zypper --non-interactive install -y "$TELEPORT_PACKAGE" jq "$TELEPORT_UPDATER_PACKAGE"
elif [ "$target_version" == "none" ]; then
# no target version advertised
sudo zypper --non-interactive install -y "$TELEPORT_PACKAGE" jq "$TELEPORT_UPDATER_PACKAGE"
else
# successfully retrieved target version
sudo zypper --non-interactive install -y "$TELEPORT_PACKAGE-$target_version" jq "$TELEPORT_UPDATER_PACKAGE-$target_version"
fi
else
# no automatic upgrades
sudo zypper --non-interactive install -y "$TELEPORT_PACKAGE" jq
fi
else
echo "Unsupported distro: $ID"
exit 1
fi
if on_azure; then
API_VERSION=$(curl -m5 -sS -H "Metadata: true" --noproxy "*" "http://169.254.169.254/metadata/versions" | jq -r ".apiVersions[-1]")
INSTANCE_INFO=$(curl -m5 -sS -H "Metadata: true" --noproxy "*" "http://169.254.169.254/metadata/instance?api-version=$API_VERSION&format=json")
REGION="$(echo "$INSTANCE_INFO" | jq -r .compute.location)"
RESOURCE_GROUP="$(echo "$INSTANCE_INFO" | jq -r .compute.resourceGroupName)"
SUBSCRIPTION_ID="$(echo "$INSTANCE_INFO" | jq -r .compute.subscriptionId)"
VM_ID="$(echo "$INSTANCE_INFO" | jq -r .compute.vmId)"
JOIN_METHOD=azure
LABELS="teleport.internal/vm-id=${VM_ID},teleport.internal/subscription-id=${SUBSCRIPTION_ID},teleport.internal/region=${REGION},teleport.internal/resource-group=${RESOURCE_GROUP}"
elif on_ec2; then
IMDS_TOKEN=$(curl -m5 -sS -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 300")
INSTANCE_INFO=$(curl -m5 -sS -H "X-aws-ec2-metadata-token: ${IMDS_TOKEN}" "http://169.254.169.254/latest/dynamic/instance-identity/document")
ACCOUNT_ID="$(echo "$INSTANCE_INFO" | jq -r .accountId)"
INSTANCE_ID="$(echo "$INSTANCE_INFO" | jq -r .instanceId)"
REGION="$(echo "$INSTANCE_INFO" | jq -r .region)"
JOIN_METHOD=iam
LABELS="teleport.dev/instance-id=${INSTANCE_ID},teleport.dev/account-id=${ACCOUNT_ID},teleport.dev/region=${REGION}"
elif on_gcp; then
NAME="$(curl -m5 -sS -H "Metadata-Flavor:Google" "http://metadata.google.internal/computeMetadata/v1/instance/name")"
# GCP metadata returns fully qualified zone ("projects/<project-id>/zones/<zone>"), so we need to parse the zone name.
FULL_ZONE="$(curl -m5 -sS -H "Metadata-Flavor:Google" "http://metadata.google.internal/computeMetadata/v1/instance/zone")"
ZONE="$(basename $FULL_ZONE)"
PROJECT_ID=$(curl -m5 -sS -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/project/project-id")
JOIN_METHOD=gcp
LABELS="teleport.internal/name=${NAME},teleport.internal/zone=${ZONE},teleport.internal/project-id=${PROJECT_ID}"
else
echo "Could not determine cloud provider"
exit 1
fi
# generate /etc/default/teleport environment file
echo 'ARGS="--fips --config=/etc/teleport.yaml --pid-file=/var/run/teleport.pid --diag-addr=0.0.0.0:3434"' | sudo tee /etc/default/teleport
# generate /etc/systemd/system/teleport.service file
echo '[Unit]
Description=Teleport Service installed by Teleport EC2 Discovery Service
After=network.target
[Service]
Type=simple
Restart=on-failure
EnvironmentFile=-/etc/default/teleport
ExecStart=/usr/local/bin/teleport start $ARGS
ExecReload=/bin/kill -HUP $MAINPID
PIDFile=/run/teleport.pid
LimitNOFILE=524288
[Install]
WantedBy=multi-user.target' | sudo tee /etc/systemd/system/teleport.service
# generate teleport ssh config
# token is read as a parameter from the AWS ssm script run and
# passed as the first argument to the script
sudo /usr/local/bin/teleport node configure \
--proxy="{{ .PublicProxyAddr }}" \
--join-method=${JOIN_METHOD} \
{{- if .AzureClientID }}
--azure-client-id="{{ .AzureClientID }}" \
{{ end -}}
--token="$1" \
--output=file \
--labels="${LABELS}"
# change log output to json format
sudo sed -i "s/ output: text/ output: json/" /etc/teleport.yaml
# enable and start teleport service
sudo systemctl enable --now teleport
) 9>/var/lock/teleport_install.lock
You can see I added -fips
to TELEPORT_PACKAGE
and created /etc/default/teleport
with --fips
in ARGS. You can create the installer using the command tctl create -f installer.yaml
, then in your Discovery config, just update the script_name
to the new installer script. Feel free to ping @James Nguyen
in Teleport Community Slack if you want to discuss more.
Thank you very much!
Expected behavior:
Current behavior:
Bug details: