Skip to content

Commit

Permalink
ci: Decouple ipsec-key-rotate action from conn-disrupt-test action
Browse files Browse the repository at this point in the history
So in future we can add encryption leak detection right after key
rotation to avoid certain issues.

ci-ipsec-e2e and ci-eks also has been adjusted to use
conn-disrupt-test-* actions before and after ipsec-key-rotate action.

Signed-off-by: gray <gray.liang@isovalent.com>
  • Loading branch information
jschwinger233 authored and pchaigno committed Jun 10, 2024
1 parent 0f957a7 commit c430572
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 70 deletions.
130 changes: 62 additions & 68 deletions .github/actions/ipsec-key-rotate/action.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: IPsec key rotation test
description: Rotates keys and checks that established connections are not interrupted
name: IPsec key rotation
description: Rotates IPsec keys
inputs:
key-algo:
required: true
Expand All @@ -17,81 +17,75 @@ inputs:
required: true
type: string
description: "'true' if encryption-overlay is enabled"
extra-connectivity-test-flags:
required: false
type: string
runs:
using: composite
steps:
- name: Rotate IPsec Key & Test
uses: ./.github/actions/conn-disrupt-test
with:
job-name: conformance-ipsec-e2e-key-rotation
extra-connectivity-test-flags: ${{ inputs.extra-connectivity-test-flags }}
operation-cmd: |
KEYID=$(kubectl get secret -n kube-system cilium-ipsec-keys -o go-template --template={{.data.keys}} | base64 -d | grep -oP "^\d+")
if [[ $KEYID -ge 15 ]]; then KEYID=0; fi
- name: Rotate IPsec Key
shell: bash
run: |
KEYID=$(kubectl get secret -n kube-system cilium-ipsec-keys -o go-template --template={{.data.keys}} | base64 -d | grep -oP "^\d+")
if [[ $KEYID -ge 15 ]]; then KEYID=0; fi
if [[ "${{ inputs.key-algo }}" == "gcm(aes)" ]]; then
key="rfc4106(gcm(aes)) $(dd if=/dev/urandom count=20 bs=1 2> /dev/null | xxd -p -c 64) 128"
elif [[ "${{ inputs.key-algo }}" == "cbc(aes)" ]]; then
key="hmac(sha256) $(dd if=/dev/urandom count=32 bs=1 2> /dev/null| xxd -p -c 64) cbc(aes) $(dd if=/dev/urandom count=32 bs=1 2> /dev/null| xxd -p -c 64)"
else
echo "Invalid key type"; exit 1
fi
data="{\"stringData\":{\"keys\":\"$((($KEYID+1)))${{ inputs.key-type-two }} ${key}\"}}"
if [[ "${{ inputs.key-algo }}" == "gcm(aes)" ]]; then
key="rfc4106(gcm(aes)) $(dd if=/dev/urandom count=20 bs=1 2> /dev/null | xxd -p -c 64) 128"
elif [[ "${{ inputs.key-algo }}" == "cbc(aes)" ]]; then
key="hmac(sha256) $(dd if=/dev/urandom count=32 bs=1 2> /dev/null| xxd -p -c 64) cbc(aes) $(dd if=/dev/urandom count=32 bs=1 2> /dev/null| xxd -p -c 64)"
else
echo "Invalid key type"; exit 1
fi
data="{\"stringData\":{\"keys\":\"$((($KEYID+1)))${{ inputs.key-type-two }} ${key}\"}}"
echo "Updating IPsec secret with $data"
kubectl patch secret -n kube-system cilium-ipsec-keys -p="$data" -v=1
echo "Updating IPsec secret with $data"
kubectl patch secret -n kube-system cilium-ipsec-keys -p="$data" -v=1
# Compute number of expected keys during key rotation depending on
# whether we use the single-key system (1 key) or the per-tunnel
# keys system (8 keys, 2x2 IPv4 and 2x2 IPv6).
# If encryption-overlay is enabled, we have 4 more IPv4 keys for the overlay.
# Transition from single-key to per-tunnel keys goes like this 1 > 9(13) > 8(12).
# Transition from per-tunnel to single-key goes like this 8(12) > 9(13) > 1.
# Transition from per-tunnel keys to per-tunnel keys goes like this 8(12) > 16(24) > 8(12).
exp_nb_keys=2
if [[ "${{ inputs.key-type-one }}" == "+" ]]; then
((exp_nb_keys+=7))
if [[ "${{ inputs.encryption-overlay }}" == "true" ]]; then
((exp_nb_keys+=4))
fi
# Compute number of expected keys during key rotation depending on
# whether we use the single-key system (1 key) or the per-tunnel
# keys system (8 keys, 2x2 IPv4 and 2x2 IPv6).
# If encryption-overlay is enabled, we have 4 more IPv4 keys for the overlay.
# Transition from single-key to per-tunnel keys goes like this 1 > 9(13) > 8(12).
# Transition from per-tunnel to single-key goes like this 8(12) > 9(13) > 1.
# Transition from per-tunnel keys to per-tunnel keys goes like this 8(12) > 16(24) > 8(12).
exp_nb_keys=2
if [[ "${{ inputs.key-type-one }}" == "+" ]]; then
((exp_nb_keys+=7))
if [[ "${{ inputs.encryption-overlay }}" == "true" ]]; then
((exp_nb_keys+=4))
fi
if [[ "${{ inputs.key-type-two }}" == "+" ]]; then
((exp_nb_keys+=7))
if [[ "${{ inputs.encryption-overlay }}" == "true" ]]; then
((exp_nb_keys+=4))
fi
fi
if [[ "${{ inputs.key-type-two }}" == "+" ]]; then
((exp_nb_keys+=7))
if [[ "${{ inputs.encryption-overlay }}" == "true" ]]; then
((exp_nb_keys+=4))
fi
fi
# Wait until key rotation starts
# We expect the amount of keys in use to grow during rotation.
while true; do
keys_in_use=$(kubectl -n kube-system exec daemonset/cilium -c cilium-agent -- cilium-dbg encrypt status | awk '/Keys in use/ {print $NF}')
if [[ $keys_in_use == $exp_nb_keys ]]; then
break
fi
echo "Waiting until key rotation starts (seeing $keys_in_use keys, expected $exp_nb_keys)"
sleep 30s
done
# Wait until key rotation starts
# We expect the amount of keys in use to grow during rotation.
while true; do
keys_in_use=$(kubectl -n kube-system exec daemonset/cilium -c cilium-agent -- cilium-dbg encrypt status | awk '/Keys in use/ {print $NF}')
if [[ $keys_in_use == $exp_nb_keys ]]; then
break
fi
echo "Waiting until key rotation starts (seeing $keys_in_use keys, expected $exp_nb_keys)"
sleep 30s
done
exp_nb_keys=1
if [[ "${{ inputs.key-type-two }}" == "+" ]]; then
exp_nb_keys=8
if [[ "${{ inputs.encryption-overlay }}" == "true" ]]; then
exp_nb_keys=12
fi
exp_nb_keys=1
if [[ "${{ inputs.key-type-two }}" == "+" ]]; then
exp_nb_keys=8
if [[ "${{ inputs.encryption-overlay }}" == "true" ]]; then
exp_nb_keys=12
fi
fi
# Wait until key rotation completes
# By default the key rotation cleanup delay is 5min, let's sleep 4min before actively polling
sleep $((4*60))
while true; do
keys_in_use=$(kubectl -n kube-system exec daemonset/cilium -c cilium-agent -- cilium-dbg encrypt status | awk '/Keys in use/ {print $NF}')
if [[ $keys_in_use == $exp_nb_keys ]]; then
break
fi
echo "Waiting until key rotation completes (seeing $keys_in_use keys, expected $exp_nb_keys)"
sleep 30s
done
# Wait until key rotation completes
# By default the key rotation cleanup delay is 5min, let's sleep 4min before actively polling
sleep $((4*60))
while true; do
keys_in_use=$(kubectl -n kube-system exec daemonset/cilium -c cilium-agent -- cilium-dbg encrypt status | awk '/Keys in use/ {print $NF}')
if [[ $keys_in_use == $exp_nb_keys ]]; then
break
fi
echo "Waiting until key rotation completes (seeing $keys_in_use keys, expected $exp_nb_keys)"
sleep 30s
done
12 changes: 11 additions & 1 deletion .github/workflows/conformance-eks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -342,15 +342,25 @@ jobs:
--junit-file "cilium-junits/${{ env.job_name }} (${{ join(matrix.*, ', ') }}) - 1.xml" \
--junit-property github_job_step="Run connectivity test (${{ join(matrix.*, ', ') }})"
- name: Setup conn-disrupt-test before rotating (${{ join(matrix.*, ', ') }})
if: ${{ matrix.ipsec == true }}
uses: ./.github/actions/conn-disrupt-test-setup

- name: Run IPsec key rotation tests (${{ join(matrix.*, ', ') }})
if: ${{ matrix.ipsec == true }}
uses: ./.github/actions/ipsec-key-rotate
with:
extra-connectivity-test-flags: ${{ steps.vars.outputs.connectivity_test_defaults }}
key-algo: "gcm(aes)"
key-type-one: ""
key-type-two: ""

- name: Check conn-disrupt-test after rotating (${{ join(matrix.*, ', ') }})
if: ${{ matrix.ipsec == true }}
uses: ./.github/actions/conn-disrupt-test-check
with:
full-test: 'true'
extra-connectivity-test-flags: ${{ steps.vars.outputs.connectivity_test_defaults }}

- name: Post-test information gathering
if: ${{ !success() && steps.install-cilium.outcome != 'skipped' }}
run: |
Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/conformance-ipsec-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -319,14 +319,22 @@ jobs:
--junit-property github_job_step="Run tests (${{ join(matrix.*, ', ') }})" \
--flush-ct
- name: Rotate IPsec Key & Test (${{ join(matrix.*, ', ') }})
- name: Setup conn-disrupt-test before rotating (${{ join(matrix.*, ', ') }})
uses: ./.github/actions/conn-disrupt-test-setup

- name: Rotate IPsec Key (${{ join(matrix.*, ', ') }})
uses: ./.github/actions/ipsec-key-rotate
with:
key-algo: ${{ matrix.key-two }}
key-type-one: ${{ matrix.key-type-one }}
key-type-two: ${{ matrix.key-type-two }}
encryption-overlay: ${{ matrix.encryption-overlay }}

- name: Check conn-disrupt-test after rotating (${{ join(matrix.*, ', ') }})
uses: ./.github/actions/conn-disrupt-test-check
with:
full-test: 'true'

- name: Fetch artifacts
if: ${{ !success() }}
shell: bash
Expand Down

0 comments on commit c430572

Please sign in to comment.