feat(linux): gate custom cloud cert pull on RCV 1P opt-in#7958
feat(linux): gate custom cloud cert pull on RCV 1P opt-in#7958
Conversation
- add opt-in check via acms/isOptedInForRootCerts before certificate retrieval - use operation-request endpoints for RCV 1P root/intermediate certificate pull - keep fallback to legacy cacertificates flow when not opted in - harden opt-in detection with curl --fail and JSON boolean match - normalize Flatcar cert installation by converting .crt artifacts to .pem during copy
|
@rchincha please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
|
There was a problem hiding this comment.
Pull request overview
This PR introduces RCV 1P (Root Certificate Validation 1st Party) opt-in gating for custom cloud certificate retrieval in AKS. The change modifies the init-aks-custom-cloud.sh script to check whether a VM is opted into RCV 1P via a new wireserver endpoint (/acms/isOptedInForRootCerts). When opted in, the script uses new operation-request endpoints to pull root and intermediate certificates; otherwise, it falls back to the legacy cacertificates flow.
Changes:
- Added RCV 1P opt-in detection via wireserver endpoint with JSON boolean matching
- Implemented new certificate retrieval path using
operationrequestsrootandoperationrequestsintermediateendpoints - Preserved backward compatibility with legacy certificate retrieval for non-opted-in VMs
- Normalized Flatcar certificate installation by converting .crt files to .pem during copy operation
| local operation_response | ||
|
|
||
| echo "Retrieving certificate operations for type: $endpoint_type" | ||
| operation_response=$(make_request_with_retry "${WIRESERVER_ENDPOINT}/machine?comp=acmspackage&type=$endpoint_type&ext=json") |
There was a problem hiding this comment.
The function make_request_with_retry is called but never defined in this script. This function is required for the RCV 1P opt-in path to work. Based on similar scripts like init-aks-custom-cloud-operation-requests.sh, this function should be defined before it's used. The function should implement retry logic with exponential backoff for rate limiting and network failures.
| local operation_response | ||
|
|
||
| echo "Retrieving certificate operations for type: $endpoint_type" | ||
| operation_response=$(make_request_with_retry "${WIRESERVER_ENDPOINT}/machine?comp=acmspackage&type=$endpoint_type&ext=json") |
There was a problem hiding this comment.
The variable WIRESERVER_ENDPOINT is used but never defined in this script. This will cause the script to fail when the RCV 1P opt-in path is taken. Based on similar scripts like init-aks-custom-cloud-operation-requests.sh, this should be defined as WIRESERVER_ENDPOINT="http://168.63.129.16" near the top of the script, before the function definitions.
|
|
||
| # Extract ResourceFileName values from the JSON response | ||
| local cert_filenames | ||
| mapfile -t cert_filenames < <(echo "$operation_response" | grep -oP '(?<="ResouceFileName": ")[^"]*') |
There was a problem hiding this comment.
The JSON field name is misspelled as "ResouceFileName" (missing 'r' in Resource). This should be "ResourceFileName". This typo will cause the certificate extraction to fail if the wireserver API returns the correctly spelled field name. Verify the actual field name from the wireserver API response and correct the spelling to match.
| mapfile -t cert_filenames < <(echo "$operation_response" | grep -oP '(?<="ResouceFileName": ")[^"]*') | |
| mapfile -t cert_filenames < <(echo "$operation_response" | grep -oP '(?<="ResourceFileName": ")[^"]*') |
| # Save the certificate to the appropriate location | ||
| echo "$cert_content" > "/root/AzureCACertificates/$cert_filename" | ||
| echo "Successfully saved certificate: $cert_filename" |
There was a problem hiding this comment.
When the RCV 1P opt-in path is taken, certificates are saved with their original filenames (including .crt extension) in line 81. However, the Flatcar cert installation logic at lines 143-147 attempts to copy files matching "*.crt" pattern. This creates an inconsistency: the fallback path (lines 121-124) saves files with .pem extension for Flatcar, but the RCV 1P path saves them as .crt regardless of distro. Either the cert saving logic should respect IS_FLATCAR and save as .pem, or the RCV 1P cert download should ensure filenames use appropriate extensions for each distro.
| # Save the certificate to the appropriate location | |
| echo "$cert_content" > "/root/AzureCACertificates/$cert_filename" | |
| echo "Successfully saved certificate: $cert_filename" | |
| # Determine target filename based on distro to match cert installation expectations | |
| local target_cert_filename="$cert_filename" | |
| if [ "$IS_FLATCAR" -eq 1 ]; then | |
| # For Flatcar, use .pem extension to align with fallback cert handling | |
| target_cert_filename="${filename}.pem" | |
| fi | |
| # Save the certificate to the appropriate location | |
| echo "$cert_content" > "/root/AzureCACertificates/$target_cert_filename" | |
| echo "Successfully saved certificate: $target_cert_filename" |
| certNames=($(echo $certs | grep -oP '(?<=Name\": \")[^\"]*')) | ||
| certBodies=($(echo $certs | grep -oP '(?<=CertBody\": \")[^\"]*')) |
There was a problem hiding this comment.
Variable expansions should be quoted to prevent word splitting and glob expansion. The expressions ${certBodies[@]} and ${certNames[@]} within command substitutions should have proper quoting. The use of unquoted variables in command substitution, especially with grep and sed, can lead to unexpected behavior if the data contains special characters or spaces.
| if optInCheck=$(curl -sS --fail "http://168.63.129.16/acms/isOptedInForRootCerts"); then | ||
| : | ||
| else | ||
| echo "Warning: failed to query root cert opt-in status; defaulting to non-opt-in flow" |
There was a problem hiding this comment.
The opt-in check uses curl with --fail flag which will cause curl to fail silently (exit code 22) on HTTP errors, but the captured output in optInCheck might still contain error HTML or be empty. While the grep check on line 107 will handle this gracefully by falling back to the legacy flow, it would be better to add explicit error handling or use -f (fail) with better error checking to ensure robust behavior across all failure scenarios.
| if optInCheck=$(curl -sS --fail "http://168.63.129.16/acms/isOptedInForRootCerts"); then | |
| : | |
| else | |
| echo "Warning: failed to query root cert opt-in status; defaulting to non-opt-in flow" | |
| optInCurlStatus=0 | |
| optInCheck=$(curl -sS --fail "http://168.63.129.16/acms/isOptedInForRootCerts" 2>/dev/null) || optInCurlStatus=$? | |
| if [ "$optInCurlStatus" -ne 0 ]; then | |
| echo "Warning: failed to query root cert opt-in status (curl exit code $optInCurlStatus); defaulting to non-opt-in flow" | |
| optInCheck="" |
| else | ||
| echo "Not opted in for root certs, skipping CA cert pull and install" | ||
| # http://168.63.129.16 is a constant for the host's wireserver endpoint | ||
| certs=$(curl "http://168.63.129.16/machine?comp=acmspackage&type=cacertificates&ext=json") |
There was a problem hiding this comment.
The fallback curl request to retrieve certificates lacks error handling. Unlike the RCV 1P path which uses make_request_with_retry with retry logic, this curl command has no --fail flag, no retry mechanism, and no validation of the response. If the wireserver is temporarily unavailable or rate-limits the request, the script will continue with potentially empty or malformed data, leading to provisioning failures. Consider adding retry logic and error checking similar to the RCV 1P path.
| if [ "$IS_FLATCAR" -eq 1 ]; then | ||
| ext=".pem" | ||
| fi | ||
| for i in ${!certBodies[@]}; do | ||
| echo ${certBodies[$i]} | sed 's/\\r\\n/\n/g' | sed 's/\\//g' > "/root/AzureCACertificates/$(echo ${certNames[$i]} | sed "s/.cer/.${ext}/g")" | ||
| done | ||
| echo "successfully pulled in default certs" | ||
| fi | ||
| for i in ${!certBodies[@]}; do | ||
| echo ${certBodies[$i]} | sed 's/\\r\\n/\n/g' | sed 's/\\//g' > "/root/AzureCACertificates/$(echo ${certNames[$i]} | sed "s/.cer/.${ext}/g")" | ||
| done | ||
|
|
||
| IFS=$IFS_backup | ||
|
|
||
| if [ "$IS_FLATCAR" -eq 0 ]; then | ||
| if [ "${IS_FLATCAR}" -eq 0 ]; then |
There was a problem hiding this comment.
The quote style change from "$IS_FLATCAR" to "${IS_FLATCAR}" is good for consistency, but the original comparison at line 122 still uses the old style "$IS_FLATCAR". For consistency, all IS_FLATCAR comparisons in the script should use the same quote style.
- add a dedicated CARefresh parameter set with -CARefreshOnly mode for certificate-only execution - implement RCV 1P cert retrieval from WireServer, including opt-in detection via isOptedInForRootCerts - add operation-request certificate download path (operationrequestsroot/operationrequestsintermediate) - keep backward-compatible fallback to legacy cacertificates endpoint when VM is not opted in - add retry/backoff wrapper for WireServer calls and structured RCV1P logging helper - install downloaded certs into LocalMachine certificate stores (Root for self-signed, CA for intermediates) - register a daily SYSTEM scheduled task (aks-rcv1p-cert-refresh) to rerun cert refresh via this script - wire AKS custom cloud base-prep flow to run RCV 1P refresh and task registration - document RCV 1P intent with inline comment block for maintainability
add opt-in check via acms/isOptedInForRootCerts before certificate retrieval
use operation-request endpoints for RCV 1P root/intermediate certificate pull
keep fallback to legacy cacertificates flow when not opted in
harden opt-in detection with curl --fail and JSON boolean match
normalize Flatcar cert installation by converting .crt artifacts to .pem during copy
What this PR does / why we need it:
Which issue(s) this PR fixes:
Fixes #