Skip to content

Commit

Permalink
Remove deprecated Cloud IoT backend. (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
csieber authored Mar 16, 2023
1 parent c100d5e commit 6011007
Show file tree
Hide file tree
Showing 28 changed files with 15 additions and 1,267 deletions.
1 change: 0 additions & 1 deletion bazel/build_rules/app_chart/values-cloud.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ registry: "gcr.io/my-gcp-project"
robots: []
region: example-gcp-region
# Token Vendor feature flags
use_tv_k8s_backend: false
use_tv_k8s_verbose: false
57 changes: 1 addition & 56 deletions deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -88,27 +88,6 @@ function prepare_source_install {
TAG="latest" ${DIR}/bazel-bin/src/app_charts/push "${CLOUD_ROBOTICS_CONTAINER_REGISTRY}"
}

function clear_iot_devices {
local iot_registry_name="$1"
local devices
devices=$(gcloud beta iot devices list \
--project "${GCP_PROJECT_ID}" \
--region "${GCP_REGION}" \
--registry "${iot_registry_name}" \
--format='value(id)')
if [[ -n "${devices}" ]] ; then
echo "Clearing IoT devices from ${iot_registry_name}" 1>&2
for dev in ${devices}; do
gcloud beta iot devices delete \
--quiet \
--project "${GCP_PROJECT_ID}" \
--region "${GCP_REGION}" \
--registry "${iot_registry_name}" \
${dev}
done
fi
}

function terraform_exec {
( cd "${TERRAFORM_DIR}" && ${TERRAFORM} "$@" )
}
Expand Down Expand Up @@ -180,12 +159,6 @@ private_image_repositories = ["${PRIVATE_DOCKER_PROJECTS// /\", \"}"]
EOF
fi

if [[ "${CRC_USE_TV_K8S_BACKEND}" != 1 ]]; then
cat >> "${TERRAFORM_DIR}/terraform.tfvars" <<EOF
use_cloudiot = true
EOF
fi

if [[ -n "${TERRAFORM_GCS_BUCKET:-}" ]]; then
cat > "${TERRAFORM_DIR}/backend.tf" <<EOF
# autogenerated by deploy.sh, do not edit!
Expand Down Expand Up @@ -354,17 +327,7 @@ function helm_charts {
${SYNK} init
echo "synk init done"

# Make the K8s backend the default backend for the token vendor.
# This flag implies the go token version flag.
if [[ "${CRC_USE_TV_K8S_BACKEND}" == 0 ]]; then
# only unset values are interpreted as false by our script
# needs debugging why
unset CRC_USE_TV_K8S_BACKEND
else
CRC_USE_TV_K8S_BACKEND=1
fi

values=$(cat <<EOF
values=$(cat <<EOF
--set-string domain=${CLOUD_ROBOTICS_DOMAIN}
--set-string ingress_ip=${INGRESS_IP}
--set-string project=${GCP_PROJECT_ID}
Expand All @@ -376,27 +339,10 @@ function helm_charts {
--set-string oauth2_proxy.client_id=${CLOUD_ROBOTICS_OAUTH2_CLIENT_ID}
--set-string oauth2_proxy.client_secret=${CLOUD_ROBOTICS_OAUTH2_CLIENT_SECRET}
--set-string oauth2_proxy.cookie_secret=${CLOUD_ROBOTICS_COOKIE_SECRET}
--set use_tv_k8s_backend=${CRC_USE_TV_K8S_BACKEND}
--set use_tv_verbose=${CRC_USE_TV_VERBOSE}
EOF
)

# If the K8s Token Vendor backend is selected, we migrate all
# device keys found on IoT Core to Kubernetes. It is safe to
# run the migration multiple times.
if [[ "${CRC_USE_TV_K8S_BACKEND}" == 1 ]]; then
echo "running migration from IoT Core to Kubernetes backend"
# First run a validation of the existing IoT Core device identifiers
${TV_COMMAND} \
--project ${GCP_PROJECT_ID} --region ${GCP_REGION} --registry cloud-robotics \
--validate-iot-identifiers
# Migrate the device keys to Kubernetes
${TV_COMMAND} \
--project ${GCP_PROJECT_ID} --region ${GCP_REGION} --registry cloud-robotics \
--namespace app-token-vendor \
--migrate-iot-to-k8s --migrate-k8s-ctx "${KUBE_CONTEXT}"
fi

echo "installing base-cloud to ${KUBE_CONTEXT}..."
${HELM} template -n base-cloud --namespace=${BASE_NAMESPACE} ${values} \
./bazel-bin/src/app_charts/base/base-cloud-0.0.1.tgz \
Expand Down Expand Up @@ -432,7 +378,6 @@ function delete {
if is_source_install; then
bazel ${BAZEL_FLAGS} build "@hashicorp_terraform//:terraform"
fi
clear_iot_devices "cloud-robotics"
terraform_delete
}

Expand Down
6 changes: 3 additions & 3 deletions docs/concepts/device_identity.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ services to integrate those identities into a cloud based IAM system.
The following components are part of the whole setup:
* Cloud:
* `IAM`: Cloud Identity and Access Management
* `IoT Core`: used as a Key Management Service
* `Kubernetes configmaps`: used as a Key Management Service
* `Token Vendor`: token exchange service for OAuth2 service accounts
* `robot service-account`: a GCP IAM service account that has the union of
permissions that applications running on the robot cluster require
Expand All @@ -28,7 +28,7 @@ The setup flow is used to register a new robot cluster to a cloud project.
* (1) (Admin-)user runs `Setup`, which generates a RSA key-pair and stores it as
a K8S secret
* (2) `Setup` uploads the public key to `Token Vendor`
* (3) `Token Vendor` stores key in `IoT Core` device registry
* (3) `Token Vendor` stores key in `Kubernetes`


## Authentication
Expand All @@ -44,7 +44,7 @@ on-prem robot clusters.
* (2) `Metadata Server` talks to `Token Vendor` get an Access Token for the
`robot service-account`
* (3) `Token Vendor` verifies the key the request has been signed with against
the `IoT Core` device registry
the device registry
* (4) `Token Vendor` gets an Access Token for the `robot service-account` from
`IAM`
* `Token Vendor` returns Access Token through `Metadata Server` to the
Expand Down
2 changes: 0 additions & 2 deletions docs/how-to/deploy-from-sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ token-vendor-xxx 1/1 Running 0 1m

In addition to the cluster, `deploy.sh` also created:

* the [cloud-robotics IoT Core Registry](https://console.cloud.google.com/iot/registries) that will be used to manage the list of authorized robots,
* the [[PROJECT_ID]-robot Cloud Storage bucket](https://console.cloud.google.com/storage/browser), containing the scripts that connect robots to the cloud, and
* the [Identity & Access Management policies](https://console.cloud.google.com/iam-admin/iam) that authorize robots and humans to communicate with GCP.

Expand All @@ -127,7 +126,6 @@ To apply changes made in the source code, run:
The following command will delete:
* the [cloud-robotics Kubernetes cluster](https://console.cloud.google.com/kubernetes/list)
* the [cloud-robotics IoT Core Registry](https://console.cloud.google.com/iot/registries)
This can be useful if the cluster is in a broken state.
Be careful with this invocation, since you'll have to redeploy the project and reconnect any robots afterwards.
Expand Down
2 changes: 1 addition & 1 deletion docs/how-to/using-cloud-storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Normally, to access a private Cloud Storage bucket from a robot, you'd need to m

So why was the robot able to drop a file in the non-public bucket? There is a lot going on in the background that enabled the configuration-less secure API access:

* When the robot was connected to the cloud, it generated a new private key and registered the corresponding public key in a Cloud IoT device registry.
* When the robot was connected to the cloud, it generated a new private key and registered the corresponding public key in a device registry, e.g., as Kubernetes configmaps.
* The setup-robot command also started a Metadata Server as a workload in the robot's Kubernetes cluster. You can verify it is running with `kubectl get pods`. The Metadata Server identifies itself to the cloud using the robot's private key and obtains short-lived access tokens in the background.
* Every time a client library performs a call to a Google Cloud API, it asks the local Metadata Server for an access token.
* The permissions of the robot can be inspected and managed in the Cloud Console under "IAM &amp; admin"; you will notice that there is a service account called `robot-service@[PROJECT_ID].iam.gserviceaccount.com`, which has "Storage Admin" permissions. These permissions allowed the robot to write to the private bucket.
Expand Down
2 changes: 1 addition & 1 deletion docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ How-to Guide.
### Layer 1: Robot Fleet Connectivity and Security

Layer 1 provides secure communication and access control. Every robot is identified by a unique
keypair. The public key is managed in a [Cloud IoT device registry](https://cloud.google.com/iot/docs/concepts/devices).
keypair. The public key is managed in as Kubernetes configmap.
A cloud-based authorization service uses these keys to authenticate robots and generate short-lived
OAuth access tokens.

Expand Down
3 changes: 0 additions & 3 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ token-vendor-xxx 1/1 Running 0 1m
In addition to the cluster, the install script also created:
* the [cloud-robotics IoT Core Registry][iot-registry] that will be used to manage the list of authorized robots,
* the [[PROJECT_ID]-cloud-robotics-config bucket][storage-bucket], containing a `config.sh` and a Terraform state which are necessary to update your cloud project later,
* the [[PROJECT_ID]-robot Cloud Storage bucket][storage-bucket], containing the scripts that connect robots to the cloud, and
* the [Identity & Access Management policies][iam] that authorize robots and humans to communicate with GCP.
Expand Down Expand Up @@ -112,7 +111,6 @@ curl -fS "https://storage.googleapis.com/cloud-robotics-releases/run-install.sh"
The following command will delete:
* the [cloud-robotics Kubernetes cluster](https://console.cloud.google.com/kubernetes/list)
* the [cloud-robotics IoT Core Registry](https://console.cloud.google.com/iot/registries)
This can be useful if the cluster is in a broken state.
Be careful with this invocation, since you'll have to redeploy the project and reconnect any robots afterwards.
Expand All @@ -137,7 +135,6 @@ If you want to completely shut down the project, see [the Resource Manager docum
[modify-project]: https://cloud.google.com/billing/docs/how-to/modify-project
[cloud-sdk]: https://cloud.google.com/sdk/docs/
[workloads]: https://console.cloud.google.com/kubernetes/workload
[iot-registry]: https://console.cloud.google.com/iot/registries
[storage-bucket]: https://console.cloud.google.com/storage/browser
[iam]: https://console.cloud.google.com/iam-admin/iam
[undelete-service]: https://cloud.google.com/sdk/gcloud/reference/endpoints/services/undelete
Expand Down
1 change: 0 additions & 1 deletion src/app_charts/base/cloud/app-management.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ spec:
registry={{ .Values.registry }},\
deploy_environment={{ .Values.deploy_environment }},\
region={{ .Values.region }},\
use_tv_k8s_backend={{ .Values.use_tv_k8s_backend }},\
use_tv_verbose={{ .Values.use_tv_verbose }}"
- --webhook-port=9876
- --cert-dir=/tls
Expand Down
6 changes: 0 additions & 6 deletions src/app_charts/token-vendor/cloud/token-vendor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,8 @@ spec:
{{- if eq .Values.deploy_environment "GCP-testing" }}
- --key-store=IN_MEMORY
{{- else }}
{{- if .Values.use_tv_k8s_backend }}
- --key-store=KUBERNETES
- --namespace=app-token-vendor
{{- else }}
- --key-store=CLOUD_IOT
- --region={{ .Values.region }}
- --registry=cloud-robotics
{{- end }}
{{- end }}
ports:
- name: token-vendor
Expand Down
1 change: 0 additions & 1 deletion src/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ cloud.google.com/go/iam v0.6.0 h1:nsqQC88kT5Iwlm4MeNGTpfMWddp6NB/UOLFTH6m1QfQ=
cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc=
cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc=
cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM=
cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs=
cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg=
cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic=
cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI=
Expand Down
8 changes: 4 additions & 4 deletions src/go/cmd/setup-dev/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import (
clientapi "k8s.io/client-go/tools/clientcmd/api"
)

const iotPrefix = "dev-"
const robotPrefix = "dev-"

var (
project = flag.String("project", "", "Project ID for the Google Cloud Platform")
Expand Down Expand Up @@ -137,7 +137,7 @@ func createKubeRelayEntry(projectID string, domain string, robotName string) err
return nil
}

// setupDevCredentials generates a workstation ID for use with Cloud IoT then
// setupDevCredentials generates a workstation ID for use with the Token Vendor then
// calls in to CreateAndPublishCredentialsToCloud to create and publish a private key.
func setupDevCredentials(client *http.Client, domain string, robotName string) error {
hostname, err := os.Hostname()
Expand All @@ -163,14 +163,14 @@ func setupDevCredentials(client *http.Client, domain string, robotName string) e
return nil
}

// makeIdentifier converts a string to a valid Cloud IoT ID by adding a prefix
// makeIdentifier converts a string to a valid robot identifier by adding a prefix
// and removing invalid characters.
func makeIdentifier(base string) string {
invalid, err := regexp.Compile("[^a-zA-Z0-9_.~+%-]+")
if err != nil {
log.Fatalln("makeValidIdentifier: failed to compile regex:", err)
}
return iotPrefix + invalid.ReplaceAllString(base, "")
return robotPrefix + invalid.ReplaceAllString(base, "")
}

func containerExists(container string) (bool, error) {
Expand Down
17 changes: 0 additions & 17 deletions src/go/cmd/token-vendor/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ go_library(
name = "go_default_library",
srcs = [
"main.go",
"migrate.go",
],
importpath = "github.com/googlecloudrobotics/core/src/go/cmd/token-vendor",
visibility = ["//visibility:private"],
Expand All @@ -15,7 +14,6 @@ go_library(
"//src/go/cmd/token-vendor/api/v1:go_default_library",
"//src/go/cmd/token-vendor/app:go_default_library",
"//src/go/cmd/token-vendor/oauth:go_default_library",
"//src/go/cmd/token-vendor/repository/cloudiot:go_default_library",
"//src/go/cmd/token-vendor/repository/k8s:go_default_library",
"//src/go/cmd/token-vendor/repository/memory:go_default_library",
"//src/go/cmd/token-vendor/tokensource:go_default_library",
Expand All @@ -41,18 +39,3 @@ go_binary(
name = "token-vendor",
embed = [":go_default_library"],
)

go_test(
name = "go_default_test",
srcs = ["migrate_test.go"],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
deps = [
"//src/go/cmd/token-vendor/repository/cloudiot:go_default_library",
"//src/go/cmd/token-vendor/repository/k8s:go_default_library",
"@com_github_google_go_cmp//cmp:go_default_library",
"@io_k8s_api//core/v1:go_default_library",
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
"@io_k8s_client_go//kubernetes/fake:go_default_library",
],
)
25 changes: 1 addition & 24 deletions src/go/cmd/token-vendor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ The token vendor itself is stateless and all data is stored in GCP.

The following workflows are covered by the token vendor:

* Register a robot by its public key and a unique device identifier. The public key is stored in a cloud backend (currently Cloud IoT Core device registry)
* Register a robot by its public key and a unique device identifier. The public key is stored in a cloud backend.
* Retrieve a robot's public key through the device identifier
* Generate an scoped and time-limited IAM access token for access to GCP resources
* Validate a given IAM access token
Expand All @@ -16,12 +16,6 @@ The following workflows are covered by the token vendor:

The token vendor supports multiple backends for storage of public keys for registered devices.

### Cloud IoT Backend

GCP Cloud IoT is deprecated and will be turned off in April 2023.
The Cloud IoT token vendor backend stores a key as credential.
To block a device or remove the device completely the GCP UI can be used.

### Kubernetes Configmaps

The Kubernetes backend uses configmaps to store and lookup public keys.
Expand All @@ -44,23 +38,6 @@ curl --data-binary "@api/v1/testdata/rsa_cert.pem" -H "Content-type: application
curl -D - http://127.0.0.1:9090/apis/core.token-vendor/v1/public-key.read?device-id=robot-dev-testuser
```

#### Migration from IoT to Kubernetes backend

You can run the Token Vendor with `--migrate-iot-to-k8s` to migrate all public keys
from the IoT backend to the Kubernetes backend. For this you have to set all relevant
CLI flags for both backends. Example:

```sh
bazel run //src/go/cmd/token-vendor -- --verbose --project testproject --region europe-west1 --registry cloud-robotics --namespace default --migrate-iot-to-k8s --migrate-k8s-ctx KUBECONTEXT
```

Before the migration you should run `--validate-iot-identifiers` to validate the
identifiers currently on the registry to confirm that they are valid K8s identifiers. Example:

```sh
bazel run //src/go/cmd/token-vendor -- -verbose --project testproject --region europe-west1 --registry cloud-robotics --validate-iot-identifiers
```

## API

### /public-key.publish: Robot registration
Expand Down
1 change: 0 additions & 1 deletion src/go/cmd/token-vendor/api/v1/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ go_test(
deps = [
"//src/go/cmd/token-vendor/app:go_default_library",
"//src/go/cmd/token-vendor/oauth:go_default_library",
"//src/go/cmd/token-vendor/repository/cloudiot:go_default_library",
"//src/go/cmd/token-vendor/repository/k8s:go_default_library",
"//src/go/cmd/token-vendor/tokensource:go_default_library",
"@io_k8s_api//core/v1:go_default_library",
Expand Down
2 changes: 1 addition & 1 deletion src/go/cmd/token-vendor/api/v1/testdata/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## RSA Keys

These files were generated according to [Cloud IoT key generation instructions](https://cloud.google.com/iot/docs/how-tos/credentials/keys):
These files were generated like this:

```shell
openssl genrsa -out rsa_private.pem 2048
Expand Down
Loading

0 comments on commit 6011007

Please sign in to comment.