Skip to content

Commit

Permalink
add http proxy for az aks create/update
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeldeib committed Jul 27, 2022
1 parent e52c1e9 commit f1e7850
Show file tree
Hide file tree
Showing 12 changed files with 4,661 additions and 3 deletions.
10 changes: 7 additions & 3 deletions scripts/ci/credscan/CredScanSuppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -385,14 +385,12 @@
],
"_justification": "[Network] Ignore test certs."
},

{
"file": [
"src/azure-cli/azure/cli/command_modules/network/tests/latest/recordings/test_vpn_client_package.yaml"
],
"_justification": "[Network] response body contains random value recognized as secret"
},

{
"file": [
"src\\azure-cli\\azure\\cli\\command_modules\\keyvault\\tests\\hybrid_2018_03_01\\ec256.pem",
Expand Down Expand Up @@ -559,6 +557,12 @@
"src\\azure-cli\\azure\\cli\\command_modules\\vm\\tests\\latest\\recordings\\test_vm_trusted_launch_os_disk_secure_upload.yaml"
],
"_justification": "[VM] the SAS tokens come from the temporary test resources"
},
{
"file": [
"src\\azure-cli\\azure\\cli\\command_modules\\acs\\tests\\latest\\data\\setup_proxy.sh"
],
"_justification": "Dummy self-signed certificate + private key used for testing only."
}
]
}
}
6 changes: 6 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,9 @@
- name: --azure-keyvault-kms-key-vault-resource-id
type: string
short-summary: Resource ID of Azure Key Vault.
- name: --http-proxy-config
type: string
short-summary: HTTP Proxy configuration for this cluster.
examples:
- name: Create a Kubernetes cluster with an existing SSH public key.
Expand Down Expand Up @@ -790,6 +793,9 @@
- name: --azure-keyvault-kms-key-vault-resource-id
type: string
short-summary: Resource ID of Azure Key Vault.
- name: --http-proxy-config
type: string
short-summary: HTTP Proxy configuration for this cluster.
examples:
- name: Update a kubernetes cluster with standard SKU load balancer to use two AKS created IPs for the load balancer outbound connection usage.
Expand Down
2 changes: 2 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ def load_arguments(self, _):
c.argument('linux_os_config')
c.argument('yes', options_list=['--yes', '-y'], help='Do not prompt for confirmation.', action='store_true')
c.argument('host_group_id', validator=validate_host_group_id)
c.argument('http_proxy_config')

with self.argument_context('aks update') as c:
# managed cluster paramerters
Expand Down Expand Up @@ -382,6 +383,7 @@ def load_arguments(self, _):
"--update-cluster-autoscaler", "-u"], action='store_true')
c.argument('min_count', type=int, validator=validate_nodes_count)
c.argument('max_count', type=int, validator=validate_nodes_count)
c.argument('http_proxy_config')
c.argument('nodepool_labels', nargs='*', validator=validate_nodepool_labels,
help='space-separated labels: key[=value] [key[=value] ...]. See https://aka.ms/node-labels for syntax of labels.')
c.argument('yes', options_list=['--yes', '-y'], help='Do not prompt for confirmation.', action='store_true')
Expand Down
2 changes: 2 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -1570,6 +1570,7 @@ def aks_create(
vm_set_type=None,
zones=None,
ppg=None,
http_proxy_config=None,
max_pods=0,
enable_encryption_at_host=False,
enable_ultra_ssd=False,
Expand Down Expand Up @@ -1659,6 +1660,7 @@ def aks_update(
min_count=None,
max_count=None,
nodepool_labels=None,
http_proxy_config=None,
no_wait=False,
yes=False,
aks_custom_headers=None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
ContainerServiceClient = TypeVar("ContainerServiceClient")
Identity = TypeVar("Identity")
ManagedCluster = TypeVar("ManagedCluster")
ManagedClusterHTTPProxyConfig = TypeVar("ManagedClusterHTTPProxyConfig")
ManagedClusterLoadBalancerProfile = TypeVar("ManagedClusterLoadBalancerProfile")
ManagedClusterPropertiesAutoScalerProfile = TypeVar("ManagedClusterPropertiesAutoScalerProfile")
ResourceReference = TypeVar("ResourceReference")
Expand Down Expand Up @@ -1341,6 +1342,44 @@ def get_detach_acr(self) -> Union[str, None]:
# this parameter does not need validation
return detach_acr

def get_http_proxy_config(self) -> Union[Dict, ManagedClusterHTTPProxyConfig, None]:
"""Obtain the value of http_proxy_config.
:return: dictionary, ManagedClusterHTTPProxyConfig or None
"""
# read the original value passed by the command
http_proxy_config = None
http_proxy_config_file_path = self.raw_param.get("http_proxy_config")
# validate user input
if http_proxy_config_file_path:
if not os.path.isfile(http_proxy_config_file_path):
raise InvalidArgumentValueError(
"{} is not valid file, or not accessable.".format(
http_proxy_config_file_path
)
)
http_proxy_config = get_file_json(http_proxy_config_file_path)
if not isinstance(http_proxy_config, dict):
raise InvalidArgumentValueError(
"Error reading Http Proxy Config from {}. "
"Please see https://aka.ms/HttpProxyConfig for correct format.".format(
http_proxy_config_file_path
)
)

# In create mode, try to read the property value corresponding to the parameter from the `mc` object
if self.decorator_mode == DecoratorMode.CREATE:
if (
self.mc and
hasattr(self.mc, "http_proxy_config") and
self.mc.http_proxy_config is not None
):
http_proxy_config = self.mc.http_proxy_config

# this parameter does not need dynamic completion
# this parameter does not need validation
return http_proxy_config

def get_assignee_from_identity_or_sp_profile(self) -> Tuple[str, bool]:
"""Helper function to obtain the value of assignee from identity_profile or service_principal_profile.
Expand Down Expand Up @@ -4954,6 +4993,16 @@ def set_up_identity_profile(self, mc: ManagedCluster) -> ManagedCluster:
mc.identity_profile = identity_profile
return mc

def set_up_http_proxy_config(self, mc: ManagedCluster) -> ManagedCluster:
"""Set up http proxy config for the ManagedCluster object.
:return: the ManagedCluster object
"""
self._ensure_mc(mc)

mc.http_proxy_config = self.context.get_http_proxy_config()
return mc

def set_up_auto_upgrade_profile(self, mc: ManagedCluster) -> ManagedCluster:
"""Set up auto upgrade profile for the ManagedCluster object.
Expand Down Expand Up @@ -5071,6 +5120,7 @@ def construct_mc_profile_default(self, bypass_restore_defaults: bool = False) ->
mc = self.set_up_defender(mc)
# set up azure keyvalut kms
mc = self.set_up_azure_keyvault_kms(mc)
mc = self.set_up_http_proxy_config(mc)

# DO NOT MOVE: keep this at the bottom, restore defaults
if not bypass_restore_defaults:
Expand Down Expand Up @@ -5677,6 +5727,16 @@ def update_auto_upgrade_profile(self, mc: ManagedCluster) -> ManagedCluster:
mc.auto_upgrade_profile.upgrade_channel = auto_upgrade_channel
return mc

def update_http_proxy_config(self, mc: ManagedCluster) -> ManagedCluster:
"""Set up http proxy config for the ManagedCluster object.
:return: the ManagedCluster object
"""
self._ensure_mc(mc)

mc.http_proxy_config = self.context.get_http_proxy_config()
return mc

def update_identity(self, mc: ManagedCluster) -> ManagedCluster:
"""Update identity for the ManagedCluster object.
Expand Down Expand Up @@ -6008,6 +6068,8 @@ def update_mc_profile_default(self) -> ManagedCluster:
mc = self.update_azure_keyvault_kms(mc)
# update identity
mc = self.update_identity_profile(mc)
# set up http proxy config
mc = self.update_http_proxy_config(mc)
return mc

# pylint: disable=unused-argument
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# CLI test data folder

This folder contains test data for some AKS CLI commands.

For HTTP proxy testing, we need a preknown certificate which we will present to AKS
and also inject to a VM for use in a proxy server. We can't generate the certificate
at VM deploy time because we won't be able to extract it easily to pass back to AKS
without e.g. VM run-command which is slow. So we generate the certificate here and
hardcode the key/cert into a VM provisioning script.

The existing cert is a self-signed CA with a 10 year expiry (Not After: Mar 5 16:44:47 2032 GMT) with a SAN of the
proxy server hostname.

You can regenerate it with the following openssl commands in bash.

After regenerating it, update the certificate in httpproxyconfig.json used for cluster creation,
and the hardcoded key/cert in setup_proxy.sh.

The cert in httpproxyconfig_update.json can be generated the same way, but it should not need to be updated.

```bash
# Name of the VM on which proxy is hosted
HOST="cli-proxy-vm"

CONFIG="
[req]
distinguished_name=dn
[ dn ]
[ ext ]
basicConstraints=CA:TRUE,pathlen:0
"

openssl req -config <(echo "$CONFIG") -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout squidk.pem -out squidc.pem -subj "/CN=${HOST}" -addext "subjectAltName=DNS:${HOST}" -addext "basicConstraints=critical,CA:TRUE,pathlen:0" -addext "keyUsage=critical,keyCertSign,cRLSign,keyEncipherment,encipherOnly,decipherOnly,digitalSignature,nonRepudiation" -addext "extendedKeyUsage=clientAuth,serverAuth"

# update cert in testdata file
jq --arg cert "$(cat squidc.pem | base64 -w 0)" '.trustedCa=$cert' httpproxyconfig.json | sponge httpproxyconfig.json
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"httpProxy": "http://cli-proxy-vm:3128/",
"httpsProxy": "https://cli-proxy-vm:3129/",
"noProxy": [
"localhost",
"127.0.0.1"
],
"trustedCa": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZHekNDQXdPZ0F3SUJBZ0lVT1FvajhDTFpkc2Vscjk3cnZJd3g1T0xEc3V3d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0Z6RVZNQk1HQTFVRUF3d01ZMnhwTFhCeWIzaDVMWFp0TUI0WERUSXlNRE13T0RFMk5EUTBOMW9YRFRNeQpNRE13TlRFMk5EUTBOMW93RnpFVk1CTUdBMVVFQXd3TVkyeHBMWEJ5YjNoNUxYWnRNSUlDSWpBTkJna3Foa2lHCjl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUEvTVB0VjVCVFB0NmNxaTRSZE1sbXIzeUlzYTJ1anpjaHh2NGgKanNDMUR0blJnb3M1UzQxUEgwcmkrM3RUU1ZYMzJ5cndzWStyRDFZUnVwbTZsbUU3R2hVNUkwR2k5b3prU0YwWgpLS2FKaTJveXBVL0ZCK1FQcXpvQ1JzTUV3R0NibUtGVmw4VnVoeW5kWEs0YjRrYmxyOWJsL2V1d2Q3TThTYnZ6CldVam5lRHJRc2lJc3J6UFQ0S0FaTHFjdHpEZTRsbFBUN1lLYTMzaGlFUE9mdldpWitkcWthUUE5UDY0eFhTeW4KZkhYOHVWQUozdUJWSmVHeEQwcGtOSjdqT3J5YVV1SEh1Y1U4UzltSWpuS2pBQjVhUGpMSDV4QXM2bG1iMzEyMgp5KzF0bkVBbVhNNTBEK1VvRWpmUzZIT2I1cmRpcVhHdmMxS2JvS2p6a1BDUnh4MmE3MmN2ZWdVajZtZ0FKTHpnClRoRTFsbGNtVTRpemd4b0lNa1ZwR1RWT0xMbjFWRkt1TmhNWkN2RnZLZ25Lb0F2M0cwRlVuZldFYVJSalNObUQKTFlhTURUNUg5WnQycERJVWpVR1N0Q2w3Z1J6TUVuWXdKTzN5aURwZzQzbzVkUnlzVXlMOUpmRS9OaDdUZzYxOApuOGNKL1c3K1FZYllsanVyYXA4cjdRRlNyb2wzVkNoRkIrT29yNW5pK3ZvaFNBd0pmMFVsTXBHM3hXbXkxVUk0ClRGS2ZGR1JSVHpyUCs3Yk53WDVoSXZJeTVWdGd5YU9xSndUeGhpL0pkeHRPcjJ0QTVyQ1c3K0N0Z1N2emtxTkUKWHlyN3ZrWWdwNlk1TFpneTR0VWpLMEswT1VnVmRqQk9oRHBFenkvRkY4dzFGRVZnSjBxWS9yV2NMa0JIRFQ4Ugp2SmtoaW84Q0F3RUFBYU5mTUYwd0Z3WURWUjBSQkJBd0RvSU1ZMnhwTFhCeWIzaDVMWFp0TUJJR0ExVWRFd0VCCi93UUlNQVlCQWY4Q0FRQXdEd1lEVlIwUEFRSC9CQVVEQXdmbmdEQWRCZ05WSFNVRUZqQVVCZ2dyQmdFRkJRY0QKQWdZSUt3WUJCUVVIQXdFd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dJQkFBb21qQ3lYdmFRT3hnWUs1MHNYTEIyKwp3QWZkc3g1bm5HZGd5Zmc0dXJXMlZtMTVEaEd2STdDL250cTBkWXkyNE4vVWJHN1VEWHZseUxJSkZxMVhQN25mCnBaRzBWQ2paNjlibXhLbTNaOG0wL0F3TXZpOGU5ZWR5OHY5a05CQ3dMR2tIYkE4WW85Q0lpUWdlbGZwcDF2VWgKYm5OQmhhRCtpdTZDZmlDTHdnSmIvaXc3ZW8vQ3lvWnF4K3RqWGFPMnpYdm00cC8rUUlmQU9ndEdRTEZVOGNmWgovZ1VyVHE1Z0ZxMCtQOUd5V3NBVEpGNnE3TDZXWlpqME91VHNlN2Y0Q1NpajZNbk9NTXhBK0pvYWhKejdsc1NpClRKSEl3RXA1ci9SeWhweWVwUXhGWWNVSDVKSmY5cmFoWExXWmkrOVRqeFNNMll5aHhmUlBzaVVFdUdEb2s3OFEKbS9RUGlDaTlKSmIxb2NtVGpBVjh4RFNob2NpdlhPRnlobjZMbjc3dkxqWStBYXZ0V0RoUXRocHVQeHNMdFZ6bQplMFNIMTFkRUxSdGI3NG1xWE9yTzdmdS8rSUJzM0pxTEUvVSt4dXhRdHZHOHZHMXlES0hIU1pxUzJoL1dzNGw0Ck5pQXNoSGdlaFFEUEJjWTl3WVl6ZkJnWnBPVU16ZERmNTB4K0ZTbFk0M1dPSkp6U3VRaDR5WjArM2t5Z3VDRjgKcm5NTFNjZXlTNGNpNExtSi9LQ1N1R2RmNlhWWXo4QkU5Z2pqanBDUDZxeTBVbFJlZldzL2lnL3djSysyYkYxVApuL1l2KzZnWGVDVEhKNzVxRElQbHA3RFJVVWswZmJNajRiSWthb2dXV2s0emYydThteFpMYTBsZVBLTktaTi9tCkdDdkZ3cjNlaSt1LzhjenA1RjdUCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"httpProxy": "http://cli-proxy-vm:3128/",
"httpsProxy": "https://cli-proxy-vm:3129/",
"noProxy": [
"localhost",
"127.0.0.1"
],
"trustedCa": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZERENDQXZTZ0F3SUJBZ0lVQlJ3cGs1eTh5ckdrNmtYTjhkSHlMRUNvaHBrd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0VqRVFNQTRHQTFVRUF3d0habTl2TFdKaGNqQWVGdzB5TVRFd01UTXdNekU1TlRoYUZ3MHpNVEV3TVRFdwpNekU1TlRoYU1CSXhFREFPQmdOVkJBTU1CMlp2YnkxaVlYSXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDCkR3QXdnZ0lLQW9JQ0FRRFcwRE9sVC9yci9xUEZIUU9lNndBNDkyVGh3VWxZaDhCQkszTW9VWVZLNjEvL2xXekEKeFkrYzlmazlvckUrZXhMSVpwdUg1VnNZR21MNUFyc05sVmNBMkU4MWgwSlBPYUo1eEpiZG40YldpZG9vdXRVVwpXeDNhYUJLSEt0RWdZbUNmTjliWXlZMlNWRWQvNS9HeGh0akVabHJ1aEtRdkZVa3hwR0xKK1JRQ25oNklZakQwCnNpQ0YyTjJhVUJ4RE5KaUdmeHlHSVIrY2p4Vlcrd01md05CQ0l6QVkxMnY4WmpzUXdmUWlhOE5oWEx3M0tuRm0KdzUrcHN2bU1HL1FFUUtZMXNOTnk2dS9DZkI3cmIxQ0EwcjdNNnFsNFMrWHJjZUVRcXpDUWR6NWJueGNYbmFkbwp5MDlhdm5OSGRqbmpvcHNPSkxhd2hzb3RGNWFrL1FLdjYzdU9yVFFlOHlPSWlCZ3JSUzdwejcxbVlhRGNMcXFtCmtmdDVLYnFnMHNZYmo0M09LSm5aZ3crTUtackhoSFJKNi9BcWxOclZML3pFUytHU0ozQ1lSaE5nYXdDQ0Nqd1gKanZYZnkycWFEV2NQbWZaSWVVMVNzdE05THBVRWFQNjJzUVNmb3NEdnZFbUFyUVgwcmd1WGhvZ3pRUFdGWVlEKwo4SUNFYkNFc21hVnN3MzhVUzgzbFlGVCtyTHh3cm5UK1JXSUZ2WFRXbHhCNm5JeWpsOXBhNzlkdU5ocjJxN2RzCjVOU3ZWWHg5UGNqVTQ2VUZ6QnVTbUl0Q0M0Y1NadFRWc3l6ZnpMd2hKbGlqV0czTkp5TnpHUkZQcUpQdTNJUzEKZ3VtKytqdWx4bXZNWm1vM1RqSE5JRm90a0kyd3d3ZUtIcWpYcW9STmwvVnZobE5CaXZRR2gxeGovd0lEQVFBQgpvMW93V0RBU0JnTlZIUkVFQ3pBSmdnZG1iMjh0WW1GeU1CSUdBMVVkRXdFQi93UUlNQVlCQWY4Q0FRQXdEd1lEClZSMFBBUUgvQkFVREF3Zm5nREFkQmdOVkhTVUVGakFVQmdnckJnRUZCUWNEQWdZSUt3WUJCUVVIQXdFd0RRWUoKS29aSWh2Y05BUUVMQlFBRGdnSUJBTDF3RlpTdUw4NTM3aHpUTXhSUWJjcWdEU2F4RUd0ZDJaNTVCcnVWQVloagpxQjR6STd1UVZ2SkNpeXdmQm5BNnZmejh2UDBzdGJJbkVtajh1dS9CSS81NzZqR0tWUWRQSDhqMnQvN1NQWjFKClhBWk9wc1hoVll2RmtpQlhVeW1RMnAvRjFqb2ZRRE1JQ0htdHhRUSthakJQNjBpcnFnVnpsRi95NlQySUgzOHYKbGordndIam52WW5vVmhGNEY0TlE5amp6S3Y1NUhVTk0xUEJKZkFaOTJqeXovczdPMmN2cjhNWlNkT2s5QVk1RQp5RXRlQjBTSjdLS0tUZklBVmVMQzdrRnBHR3FsRkRBNzhPSS9YakNZViswRjk4MHdNOVkxTEVUa3ZMamVSMEFyCnVzZDNIS1Vtd2EwTVEwUTNZNGxma0ZtNjJTclhvcjJURC9WZHpFZWNOTnVmV1VJTVNuaEJDNTVHWjBOTVYvR0QKRXhGZTVWQkhUZEZVNlIwb3JCOVFjVll1Mzk0MEt5NXhkbHNaUHZlMmRJNS9WOXhzY0Zad3cxWWs4K21RK3NVeQp2UVBoL2ZmK0tTQjdVVkdvTVNXUlg3YjFFMGVzZSs4QzZlaVV2OXpDR0VRbkVCcnFIQWxSUDJ2ZzQ0bXFJSnRzCjN2NUt1NW0ySmJoeWNsQVR3VUNQZkN3a2tLRTg0MzZGRitDK0ZUVTJ1OWVpL2t5QTAxYi9zRFl2cWdsS2FWK3MKbEVHRkhjd05Ea2VrS1BFUEZxNkpnZ3R0WlNidE5SMnFadzl3cExIbDVuVlVXdnBGa2hvcW1KVkphK0VBSTQ1LwpqRkh4VG9PMHp1NlBxc1p5SnM2TC84Z3BhbTcwMDV6b0VETVRjcFltMlduMFBKcEg3NE9zUHJVRDVJWVA5ZEt5Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
}
Loading

0 comments on commit f1e7850

Please sign in to comment.