diff --git a/.gitignore b/.gitignore index 185172ce..acab9923 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,4 @@ asm/ .key .pem certs/ -test/test.conf \ No newline at end of file +test/test.conf diff --git a/ingress/single-cluster/ingress-cloudarmor/cleanup.sh b/ingress/single-cluster/ingress-cloudarmor/cleanup.sh new file mode 100755 index 00000000..b4e822f0 --- /dev/null +++ b/ingress/single-cluster/ingress-cloudarmor/cleanup.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-cloudarmor" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +ingress_name="cloudarmor-test" +fr=$(get_forwarding_rule "${ingress_name}" "${test_name}" "${context}") +thp=$(get_target_http_proxy "${ingress_name}" "${test_name}" "${context}") +thsp=$(get_target_https_proxy "${ingress_name}" "${test_name}" "${context}") +um=$(get_url_map "${ingress_name}" "${test_name}" "${context}") +backends=$(get_backends "${ingress_name}" "${test_name}" "${context}") +negs=$(get_negs "${context}") + +resource_yaml="ingress/single-cluster/ingress-cloudarmor/cloudarmor-ingress.yaml" +kubectl --context "${context}" delete -f "${resource_yaml}" -n "${test_name}" || true +kubectl --context "${context}" delete namespace "${test_name}" || true +wait_for_glbc_deletion "${fr}" "${thp}" "${thsp}" "${um}" "${backends}" "${negs}" + +policy_name="allow-my-ip" +sed -i'.bak' "s/${policy_name}/\$POLICY_NAME/g" "${resource_yaml}" +rm -f "${resource_yaml}".bak +gcloud compute security-policies delete "${policy_name}" --quiet || true + +cleanup_gke_basic "${test_name}" "${zone}" "${subnet_region}" diff --git a/ingress/single-cluster/ingress-cloudarmor/run-test.sh b/ingress/single-cluster/ingress-cloudarmor/run-test.sh new file mode 100755 index 00000000..ed82a7c7 --- /dev/null +++ b/ingress/single-cluster/ingress-cloudarmor/run-test.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-cloudarmor" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +vip=$(wait_for_ingress_ip "cloudarmor-test" "${test_name}" "${context}") +echo "Load balancer IP is ${vip}" + +check_http_status "${vip}/whereami" 200 +check_http_status "${vip}" 404 +check_http_status "${vip}/whereami" 502 "" "${test_name}" "${zone}" +check_http_status "${vip}" 404 "" "${test_name}" "${zone}" diff --git a/ingress/single-cluster/ingress-cloudarmor/setup.sh b/ingress/single-cluster/ingress-cloudarmor/setup.sh new file mode 100755 index 00000000..093b4b24 --- /dev/null +++ b/ingress/single-cluster/ingress-cloudarmor/setup.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-cloudarmor" +setup_gke_basic "${test_name}" "${zone}" "${subnet_region}" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +resource_yaml="ingress/single-cluster/ingress-cloudarmor/cloudarmor-ingress.yaml" +kubectl --context "${context}" create namespace "${test_name}" + +currentIP=$(curl -s ifconfig.me) +policy_name="allow-my-ip" +gcloud compute security-policies create "${policy_name}" +gcloud compute security-policies rules update 2147483647 --security-policy "${policy_name}" --action "deny-502" # Update the default policy(2147483647 is the priority value for default rule). +gcloud compute security-policies rules create 1000 --security-policy "${policy_name}" --src-ip-ranges "${currentIP}" --action "allow" +sed -i'.bak' "s/\$POLICY_NAME/${policy_name}/g" "${resource_yaml}" + +kubectl --context "${context}" apply -f "${resource_yaml}" -n "${test_name}" diff --git a/ingress/single-cluster/ingress-custom-default-backend/cleanup.sh b/ingress/single-cluster/ingress-custom-default-backend/cleanup.sh new file mode 100755 index 00000000..7c3ba777 --- /dev/null +++ b/ingress/single-cluster/ingress-custom-default-backend/cleanup.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-custom-default-backend" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +ingress_name="foo-internal" +fr=$(get_forwarding_rule "${ingress_name}" "${test_name}" "${context}") +thp=$(get_target_http_proxy "${ingress_name}" "${test_name}" "${context}") +thsp=$(get_target_https_proxy "${ingress_name}" "${test_name}" "${context}") +um=$(get_url_map "${ingress_name}" "${test_name}" "${context}") +backends=$(get_backends "${ingress_name}" "${test_name}" "${context}") +negs=$(get_negs "${context}") + +resource_yaml="ingress/single-cluster/ingress-custom-default-backend/ingress-custom-default-backend.yaml" +kubectl --context "${context}" delete -f "${resource_yaml}" -n "${test_name}" || true +kubectl --context "${context}" delete namespace "${test_name}" || true +wait_for_glbc_deletion "${fr}" "${thp}" "${thsp}" "${um}" "${backends}" "${negs}" + +cleanup_gke_basic "${test_name}" "${zone}" "${subnet_region}" diff --git a/ingress/single-cluster/ingress-custom-default-backend/run-test.sh b/ingress/single-cluster/ingress-custom-default-backend/run-test.sh new file mode 100755 index 00000000..01b097d6 --- /dev/null +++ b/ingress/single-cluster/ingress-custom-default-backend/run-test.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-custom-default-backend" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +vip=$(wait_for_ingress_ip "foo-internal" "${test_name}" "${context}") +echo "Load balancer IP is ${vip}" + +check_http_status "${vip}/foo" 200 "" "${test_name}" "${zone}" +check_http_status "${vip}/bar" 200 "" "${test_name}" "${zone}" diff --git a/ingress/single-cluster/ingress-custom-default-backend/setup.sh b/ingress/single-cluster/ingress-custom-default-backend/setup.sh new file mode 100755 index 00000000..b3524c5e --- /dev/null +++ b/ingress/single-cluster/ingress-custom-default-backend/setup.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-custom-default-backend" +setup_gke_basic "${test_name}" "${zone}" "${subnet_region}" +setup_ilb "${test_name}" "${subnet_region}" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +resource_yaml="ingress/single-cluster/ingress-custom-default-backend/ingress-custom-default-backend.yaml" +kubectl --context "${context}" create namespace "${test_name}" + +kubectl --context "${context}" apply -f "${resource_yaml}" -n "${test_name}" diff --git a/ingress/single-cluster/ingress-custom-http-health-check/cleanup.sh b/ingress/single-cluster/ingress-custom-http-health-check/cleanup.sh new file mode 100755 index 00000000..5482ca78 --- /dev/null +++ b/ingress/single-cluster/ingress-custom-http-health-check/cleanup.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-custom-http-health-check" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +ingress_name="hc-test" +fr=$(get_forwarding_rule "${ingress_name}" "${test_name}" "${context}") +thp=$(get_target_http_proxy "${ingress_name}" "${test_name}" "${context}") +thsp=$(get_target_https_proxy "${ingress_name}" "${test_name}" "${context}") +um=$(get_url_map "${ingress_name}" "${test_name}" "${context}") +backends=$(get_backends "${ingress_name}" "${test_name}" "${context}") +negs=$(get_negs "${context}") + +resource_yaml="ingress/single-cluster/ingress-custom-http-health-check/custom-http-hc-ingress.yaml" +kubectl --context "${context}" delete -f "${resource_yaml}" -n "${test_name}" || true +kubectl --context "${context}" delete namespace "${test_name}" || true +wait_for_glbc_deletion "${fr}" "${thp}" "${thsp}" "${um}" "${backends}" "${negs}" + +cleanup_gke_basic "${test_name}" "${zone}" "${subnet_region}" diff --git a/ingress/single-cluster/ingress-custom-http-health-check/run-test.sh b/ingress/single-cluster/ingress-custom-http-health-check/run-test.sh new file mode 100755 index 00000000..7e72bec4 --- /dev/null +++ b/ingress/single-cluster/ingress-custom-http-health-check/run-test.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-custom-http-health-check" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +vip=$(wait_for_ingress_ip "hc-test" "${test_name}" "${context}") +echo "Load balancer IP is ${vip}" + +check_http_status "${vip}" 200 diff --git a/ingress/single-cluster/ingress-custom-http-health-check/setup.sh b/ingress/single-cluster/ingress-custom-http-health-check/setup.sh new file mode 100755 index 00000000..a2ebf866 --- /dev/null +++ b/ingress/single-cluster/ingress-custom-http-health-check/setup.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-custom-http-health-check" +setup_gke_basic "${test_name}" "${zone}" "${subnet_region}" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +resource_yaml="ingress/single-cluster/ingress-custom-http-health-check/custom-http-hc-ingress.yaml" +kubectl --context "${context}" create namespace "${test_name}" + +kubectl --context "${context}" apply -f "${resource_yaml}" -n "${test_name}" diff --git a/ingress/single-cluster/ingress-https/README.md b/ingress/single-cluster/ingress-https/README.md index 44638070..89b8a336 100644 --- a/ingress/single-cluster/ingress-https/README.md +++ b/ingress/single-cluster/ingress-https/README.md @@ -80,7 +80,7 @@ kind: FrontendConfig metadata: name: ingress-security-config spec: - sslPolicy: gke-ingress-ssl-policy + sslPolicy: gke-ingress-ssl-policy-https redirectToHttps: enabled: true ``` @@ -123,7 +123,7 @@ Created [https://www.googleapis.com/compute/v1/projects/xxx/global/addresses/gke 4. Create an SSL policy. This policy specifies a broad set of modern ciphers and requires that clients negotiate using TLS 1.2 or higher. ``` -$ gcloud compute ssl-policies create gke-ingress-ssl-policy \ +$ gcloud compute ssl-policies create gke-ingress-ssl-policy-https \ --profile MODERN \ --min-tls-version 1.2 ``` @@ -203,5 +203,5 @@ You are now ready to serve securely on the internet! ```bash $ kubectl delete -f secure-ingress.yaml $ gcloud compute addresses delete --global gke-foobar-public-ip -$ gcloud compute ssl-policies delete gke-ingress-ssl-policy +$ gcloud compute ssl-policies delete gke-ingress-ssl-policy-https ``` diff --git a/ingress/single-cluster/ingress-https/cleanup.sh b/ingress/single-cluster/ingress-https/cleanup.sh new file mode 100755 index 00000000..5e81df87 --- /dev/null +++ b/ingress/single-cluster/ingress-https/cleanup.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-https" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +ingress_name="secure-ingress" +fr=$(get_forwarding_rule "${ingress_name}" "${test_name}" "${context}") +thp=$(get_target_http_proxy "${ingress_name}" "${test_name}" "${context}") +thsp=$(get_target_https_proxy "${ingress_name}" "${test_name}" "${context}") +um=$(get_url_map "${ingress_name}" "${test_name}" "${context}") +backends=$(get_backends "${ingress_name}" "${test_name}" "${context}") +negs=$(get_negs "${context}") + +resource_yaml="ingress/single-cluster/ingress-https/secure-ingress.yaml" +kubectl --context "${context}" delete -f "${resource_yaml}" -n "${test_name}" || true +kubectl --context "${context}" delete namespace "${test_name}" || true +wait_for_glbc_deletion "${fr}" "${thp}" "${thsp}" "${um}" "${backends}" "${negs}" + +sed -i'.bak' "s/${https_record1}/foo.\${DOMAIN}.com/g" "${resource_yaml}" +sed -i'.bak' "s/${https_record2}/bar.\${DOMAIN}.com/g" "${resource_yaml}" +rm -f "${resource_yaml}".bak +gcloud compute ssl-policies delete gke-ingress-ssl-policy-https --quiet || true +gcloud compute addresses delete --global gke-foobar-public-ip --quiet || true +gcloud dns --project="${dns_project}" record-sets delete "${https_record1}" --zone="${dns_zone}" --type="A" || true +gcloud dns --project="${dns_project}" record-sets delete "${https_record2}" --zone="${dns_zone}" --type="A" || true + +cleanup_gke_basic "${test_name}" "${zone}" "${subnet_region}" diff --git a/ingress/single-cluster/ingress-https/run-test.sh b/ingress/single-cluster/ingress-https/run-test.sh new file mode 100755 index 00000000..4b53e605 --- /dev/null +++ b/ingress/single-cluster/ingress-https/run-test.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-https" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +vip=$(wait_for_ingress_ip "secure-ingress" "${test_name}" "${context}") +echo "Load balancer IP is ${vip}" + +wait_for_managed_cert "foobar-certificate" "ingress-https" "${context}" + +check_http_status "https://${https_record1}" 200 +check_http_status "https://${https_record2}" 200 +check_http_status "http://${https_record1}" 301 +check_http_status "http://${https_record2}" 301 diff --git a/ingress/single-cluster/ingress-https/secure-ingress.yaml b/ingress/single-cluster/ingress-https/secure-ingress.yaml index fabd880f..d10400a5 100644 --- a/ingress/single-cluster/ingress-https/secure-ingress.yaml +++ b/ingress/single-cluster/ingress-https/secure-ingress.yaml @@ -49,7 +49,7 @@ kind: FrontendConfig metadata: name: ingress-security-config spec: - sslPolicy: gke-ingress-ssl-policy + sslPolicy: gke-ingress-ssl-policy-https redirectToHttps: enabled: true --- diff --git a/ingress/single-cluster/ingress-https/setup.sh b/ingress/single-cluster/ingress-https/setup.sh new file mode 100755 index 00000000..400dd071 --- /dev/null +++ b/ingress/single-cluster/ingress-https/setup.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-https" +setup_gke_basic "${test_name}" "${zone}" "${subnet_region}" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +resource_yaml="ingress/single-cluster/ingress-https/secure-ingress.yaml" +kubectl --context "${context}" create namespace "${test_name}" + +static_ip_name=gke-foobar-public-ip +gcloud compute addresses create --global "${static_ip_name}" +static_ip=$(gcloud compute addresses describe --global "${static_ip_name}" --format="value(address)") +gcloud compute ssl-policies create gke-ingress-ssl-policy-https --profile MODERN --min-tls-version 1.2 +gcloud dns --project="${dns_project}" record-sets create "${https_record1}" --zone="${dns_zone}" --type="A" --ttl="14400" --rrdatas="${static_ip}" +gcloud dns --project="${dns_project}" record-sets create "${https_record2}" --zone="${dns_zone}" --type="A" --ttl="14400" --rrdatas="${static_ip}" + +sed -i'.bak' "s/foo.\${DOMAIN}.com/${https_record1}/g" "${resource_yaml}" +sed -i'.bak' "s/bar.\${DOMAIN}.com/${https_record2}/g" "${resource_yaml}" +kubectl --context "${context}" apply -f "${resource_yaml}" -n "${test_name}" diff --git a/ingress/single-cluster/ingress-iap/cleanup.sh b/ingress/single-cluster/ingress-iap/cleanup.sh new file mode 100755 index 00000000..f2cf971c --- /dev/null +++ b/ingress/single-cluster/ingress-iap/cleanup.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-iap" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +ingress_name="iap-test" +fr=$(get_forwarding_rule "${ingress_name}" "${test_name}" "${context}") +thp=$(get_target_http_proxy "${ingress_name}" "${test_name}" "${context}") +thsp=$(get_target_https_proxy "${ingress_name}" "${test_name}" "${context}") +um=$(get_url_map "${ingress_name}" "${test_name}" "${context}") +backends=$(get_backends "${ingress_name}" "${test_name}" "${context}") +negs=$(get_negs "${context}") + +resource_yaml="ingress/single-cluster/ingress-iap/iap-ingress.yaml" +kubectl --context "${context}" delete -f "${resource_yaml}" -n "${test_name}" || true +wait_for_glbc_deletion "${fr}" "${thp}" "${thsp}" "${um}" "${backends}" "${negs}" + +sed -i'.bak' "s/${iap_record}/\$DOMAIN/g" "${resource_yaml}" +rm -f "${resource_yaml}".bak +kubectl --context "${context}" delete secret iap-test -n "${test_name}" || true +kubectl --context "${context}" delete namespace "${test_name}" || true + +brand=$(get_or_create_oauth_brand) +result=( $(get_oauth_client "${brand}" "${test_name}") ) +oauth_client_name="${result[0]}" +gcloud iap oauth-clients delete "${oauth_client_name}" --brand="${brand}" --quiet || true +gcloud compute addresses delete --global "iap-test" --quiet || true +gcloud dns --project="${dns_project}" record-sets delete "${iap_record}" --zone="${dns_zone}" --type="A" || true + +cleanup_gke_basic "${test_name}" "${zone}" "${subnet_region}" diff --git a/ingress/single-cluster/ingress-iap/run-test.sh b/ingress/single-cluster/ingress-iap/run-test.sh new file mode 100755 index 00000000..59a02729 --- /dev/null +++ b/ingress/single-cluster/ingress-iap/run-test.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-iap" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +vip=$(wait_for_ingress_ip "iap-test" "${test_name}" "${context}") +echo "Load balancer IP is ${vip}" + +check_http_status "https://${iap_record}" 302 "" "" "" "insecure" diff --git a/ingress/single-cluster/ingress-iap/setup.sh b/ingress/single-cluster/ingress-iap/setup.sh new file mode 100755 index 00000000..f12bdeb1 --- /dev/null +++ b/ingress/single-cluster/ingress-iap/setup.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-iap" +setup_gke_basic "${test_name}" "${zone}" "${subnet_region}" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +resource_yaml="ingress/single-cluster/ingress-iap/iap-ingress.yaml" +kubectl --context "${context}" create namespace "${test_name}" + +static_ip_name="iap-test" +gcloud compute addresses create --global "${static_ip_name}" +static_ip=$(gcloud compute addresses describe --global "${static_ip_name}" --format="value(address)") +gcloud dns --project="${dns_project}" record-sets create "${iap_record}" --zone="${dns_zone}" --type="A" --ttl="14400" --rrdatas="${static_ip}" + +brand=$(get_or_create_oauth_brand) +result=( $(get_oauth_client "${brand}" "${test_name}") ) +client_id="${result[1]}" +secret="${result[2]}" + +kubectl --context "${context}" create secret generic iap-test \ + --from-literal=client_id="${client_id}" \ + --from-literal=client_secret="${secret}" \ + -n "${test_name}" +sed -i'.bak' "s/\$DOMAIN/${iap_record}/g" "${resource_yaml}" +kubectl --context "${context}" apply -f "${resource_yaml}" -n "${test_name}" diff --git a/ingress/single-cluster/ingress-nginx/README.md b/ingress/single-cluster/ingress-nginx/README.md index bcfa7fd1..85f10f3b 100644 --- a/ingress/single-cluster/ingress-nginx/README.md +++ b/ingress/single-cluster/ingress-nginx/README.md @@ -19,10 +19,12 @@ GKE allows customers to deploy their own Ingress Controllers instead of the stan - 1.16.5-gke.1 and later. +## Note +NGINX is not one of the GKE offering, this is just an exmaple of using custom controller. ### Networking Manifests -In this example an internal Ingress resource matches for HTTP traffic with `foo.example.com` for path `/foo` and sends it to the `foo` Service at port 8080. A public IP address is automatically provisioned by the Ngnix controller which listens for traffic on port 8080. The Ingress resource below shows that there is one host match. Any traffic which does not match this is sent to the default backend to provide 404 responses. +In this example an external Ingress resource matches for HTTP traffic with `foo.example.com` for path `/foo` and sends it to the `foo` Service at port 8080. A public IP address is automatically provisioned by the Ngnix controller which listens for traffic on port 8080. The Ingress resource below shows that there is one host match. Any traffic which does not match this is sent to the default backend to provide 404 responses. ```yaml diff --git a/ingress/single-cluster/ingress-nginx/cleanup.sh b/ingress/single-cluster/ingress-nginx/cleanup.sh new file mode 100755 index 00000000..0e7b710d --- /dev/null +++ b/ingress/single-cluster/ingress-nginx/cleanup.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-nginx" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +ingress_name="foo-external" +fr=$(get_forwarding_rule "${ingress_name}" "${test_name}" "${context}") +thp=$(get_target_http_proxy "${ingress_name}" "${test_name}" "${context}") +thsp=$(get_target_https_proxy "${ingress_name}" "${test_name}" "${context}") +um=$(get_url_map "${ingress_name}" "${test_name}" "${context}") +backends=$(get_backends "${ingress_name}" "${test_name}" "${context}") +negs=$(get_negs "${context}") + +resource_yaml="ingress/single-cluster/ingress-nginx/ingress-nginx.yaml" + +kubectl --context "${context}" delete -f "${resource_yaml}" -n "${test_name}" || true +kubectl --context "${context}" delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.0/deploy/static/provider/cloud/deploy.yaml || true +kubectl --context "${context}" delete clusterrolebinding cluster-admin-binding || true +kubectl --context "${context}" delete namespace "${test_name}" || true +wait_for_glbc_deletion "${fr}" "${thp}" "${thsp}" "${um}" "${backends}" "${negs}" + +cleanup_gke_basic "${test_name}" "${zone}" "${subnet_region}" diff --git a/ingress/single-cluster/ingress-nginx/run-test.sh b/ingress/single-cluster/ingress-nginx/run-test.sh new file mode 100755 index 00000000..a6671274 --- /dev/null +++ b/ingress/single-cluster/ingress-nginx/run-test.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-nginx" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +vip=$(wait_for_ingress_ip "foo-external" "${test_name}" "${context}") +echo "Load balancer IP is ${vip}" + +check_http_status "${vip}/foo" 200 "host: foo.example.com" diff --git a/ingress/single-cluster/ingress-nginx/setup.sh b/ingress/single-cluster/ingress-nginx/setup.sh new file mode 100755 index 00000000..07feaf64 --- /dev/null +++ b/ingress/single-cluster/ingress-nginx/setup.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit; +set -o nounset; +set -o pipefail; +set -o xtrace; + +source ./test/helper.sh +source ./test/test.conf +test_name="ingress-nginx" +setup_gke_basic "${test_name}" "${zone}" "${subnet_region}" +suffix=$(get_hash "${test_name}") +context=$(kubectl config view -o json | jq -r ".contexts[] | select(.name | test(\"-${suffix}\")).name" || true) +# Set a non-empty value for conext since --context="" will default to use current context +if [[ -z "${context}" ]]; then + context="empty-context" +fi + +resource_yaml="ingress/single-cluster/ingress-nginx/ingress-nginx.yaml" +kubectl --context "${context}" create namespace "${test_name}" + +kubectl --context "${context}" create clusterrolebinding cluster-admin-binding \ + --clusterrole cluster-admin \ + --user $(gcloud config get-value account) + +kubectl --context "${context}" apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.0/deploy/static/provider/cloud/deploy.yaml + +for ATTEMPT in $(seq 30); do + if kubectl --context "${context}" apply -f "${resource_yaml}" -n "${test_name}"; then + break + fi + sleep 10 # Wait for webhook to be fully setup. +done \ No newline at end of file diff --git a/test/README.md b/test/README.md index 8695b2be..3e575260 100644 --- a/test/README.md +++ b/test/README.md @@ -26,6 +26,11 @@ Make sure you have valid credentials for accessing GCP: gcloud auth login ``` +Make sure you have installed jq. +``` +sudo apt-get install jq +``` + Make sure you are at the root directory of the repository. ``` @@ -43,6 +48,7 @@ export SUBNET_REGION=subnet_region To run ingress-https test, you need a special project($DNS_PROJECT) that has configured DNS domain, and make sure the current service account have role/dns_admin access to that project. Create a public DNS zone(DNS_ZONE). Then set the environment variable for DNS_PROJECT, HTTPS_RECORD1, HTTPS_RECORD2, and DNS_ZONE before running generate_env.sh. Make sure these records that uses the DNS name of the created DNS zone as suffix. +To run ingress-iap test, you need to have a support email that follows the requirement described in https://cloud.google.com/iap/docs/programmatic-oauth-clients and export it as SUPPORT_EMAIL, and an IAP_RECORD that uses the DNS zone as suffix. To run a specific test, run the setup.sh, run-test.sh, and cleanup.sh in order in the recipe directory. diff --git a/test/generate_config.sh b/test/generate_config.sh index 1540fbc4..79856963 100755 --- a/test/generate_config.sh +++ b/test/generate_config.sh @@ -8,4 +8,6 @@ dns_project="${DNS_PROJECT}" dns_zone="${DNS_ZONE}" https_record1="${HTTPS_RECORD1}" https_record2="${HTTPS_RECORD2}" +iap_record="${IAP_RECORD}" +support_email="${SUPPORT_EMAIL}" EOF diff --git a/test/helper.sh b/test/helper.sh index 5d4601fd..11f9df06 100644 --- a/test/helper.sh +++ b/test/helper.sh @@ -392,10 +392,11 @@ setup_ilb() { # (Optional)Name of the test, will be used to genereate vm instance name. # If provided, request will be sent via ssh into the test instance. # (Optional)Zone of the test instance. +# (Optional)If curl skips verification for secure connection. # Returns: # 0 if the recieved HTTP response code matches the expected one within 5 minutes, 1 if not. check_http_status() { - local url expect_code extra_header test_name zone eval_cmd + local url expect_code extra_header test_name zone insecure eval_cmd url="$1" expect_code="$2" @@ -403,6 +404,7 @@ check_http_status() { extra_header="${3:-}" test_name="${4:-}" zone="${5:-}" + insecure="${6:-}" # Get the HTTP status code from the response header. if [[ -z "${test_name}" ]]; then @@ -428,9 +430,13 @@ check_http_status() { 'curl -sI -o /dev/null -w \"%{http_code}\" -H \"${extra_header}\" ${url}'" fi + if [[ "${insecure}" ]]; then + eval_cmd="${eval_cmd} -k" + fi + # 60*5s=5min local ATTEMPT - for ATTEMPT in $(seq 60); do + for ATTEMPT in $(seq 120); do local got_code got_code=$(eval ${eval_cmd} || true) if [[ "${got_code}" == "${expect_code}" ]]; then @@ -440,3 +446,33 @@ check_http_status() { done return 1 } + +# Get the Cloud OAuth brand in the project if it exists or create a new one. +# Outputs: +# OAuth brand name of the project. +get_or_create_oauth_brand() { + brand=$(gcloud iap oauth-brands list --format="value(NAME)") + if [[ -z "${brand}" ]]; then + gcloud iap oauth-brands create --application_title="gke-net-recipes" --support_email=${support_email} + brand=$(gcloud iap oauth-brands list --format="value(NAME)") + fi + echo "${brand}" +} + +# Get the OAuth client ID and secret for the given test. +# Arguments: +# The name of oauth_brand. +# Name of the test. Used to generate OAuth client name. +# Outputs: +# OAuth client name, ID, and secret. +get_oauth_client() { + local brand test_name client_info client_id secret + brand="$1" + test_name="$2" + + gcloud iap oauth-clients create "${brand}" --display_name="${test_name}" + client_info=( $(gcloud iap oauth-clients list ${brand} --format="value(NAME,SECRET)") ) + client_id=$( echo "${client_info[0]}" | sed 's/.*identityAwareProxyClients\/\(.*\)/\1/' ) + secret="${client_info[1]}" + echo "${client_info[0]} ${client_id} ${client_info[1]}" +}