Skip to content

k8s_cp nor k8s_exec cannot work with http proxy authentication. #246

Closed
kubernetes-client/python-base
#256
@itaru2622

Description

@itaru2622
SUMMARY

k8s_cp nor k8s_exec cannot work with http proxy authentication.
both can work only when http proxy need no authentiation.

I tested most patterns for http proxy auth as described in docs/kubernetes.core.k8s_xxx_module.rst

  • environment variables : K8S_AUTH_PROXY_HEADERS_BASIC_AUTH and K8S_AUTH_PROXY_HEADERS_PROXY_BASIC_AUTH
  • specifing proxy_headers block with basic_auth and proxy_basic_auth
    but always it fails by following message.

deloying pod with kubernetes.core.k8s via http proxy authentication works.

task path: /mnt/k8s.yaml:38
redirecting (type: action) kubernetes.core.k8s_exec to kubernetes.core.k8s_info
redirecting (type: action) kubernetes.core.k8s_exec to kubernetes.core.k8s_info
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root
<127.0.0.1> EXEC /bin/sh -c 'echo ~root && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp `"&& mkdir "` echo /root/.ansible/tmp/ansible-tmp-1632388824.0367606-6684-265204369558111 `" && echo ansible-tmp-1632388824.0367606-6684-265204369558111="` echo /root/.ansible/tmp/ansible-tmp-1632388824.0367606-6684-265204369558111 `" ) && sleep 0'
Loading collection cloud.common from /root/.ansible/collections/ansible_collections/cloud/common
Using module file /root/.ansible/collections/ansible_collections/kubernetes/core/plugins/modules/k8s_exec.py
<127.0.0.1> PUT /root/.ansible/tmp/ansible-local-6492mx8edj7e/tmpp1r4bfl7 TO /root/.ansible/tmp/ansible-tmp-1632388824.0367606-6684-265204369558111/AnsiballZ_k8s_exec.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1632388824.0367606-6684-265204369558111/ /root/.ansible/tmp/ansible-tmp-1632388824.0367606-6684-265204369558111/AnsiballZ_k8s_exec.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'python /root/.ansible/tmp/ansible-tmp-1632388824.0367606-6684-265204369558111/AnsiballZ_k8s_exec.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1632388824.0367606-6684-265204369558111/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
  File "/tmp/ansible_kubernetes.core.k8s_exec_payload_tngkyn7y/ansible_kubernetes.core.k8s_exec_payload.zip/ansible_collections/kubernetes/core/plugins/modules/k8s_exec.py", line 159, in execute_module
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/stream/stream.py", line 35, in _websocket_request
    return api_method(*args, **kwargs)
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/client/api/core_v1_api.py", line 994, in connect_get_namespaced_pod_exec
    return self.connect_get_namespaced_pod_exec_with_http_info(name, namespace, **kwargs)  # noqa: E501
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/client/api/core_v1_api.py", line 1101, in connect_get_namespaced_pod_exec_with_http_info
    return self.api_client.call_api(
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/client/api_client.py", line 348, in call_api
    return self.__call_api(resource_path, method,
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/client/api_client.py", line 180, in __call_api
    response_data = self.request(
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/stream/ws_client.py", line 474, in websocket_call
    raise ApiException(status=0, reason=str(e))
fatal: [localhost]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "api_key": null,
            "ca_cert": null,
            "client_cert": null,
            "client_key": null,
            "command": "/bin/sh -c 'rm -f /tmp/debian-bullseye.txt\ndate > /tmp/debian-bullseye.txt\n'",
            "container": "debian-bullseye",
            "context": null,
            "host": null,
            "kubeconfig": "/root/.kube/config",
            "namespace": "default",
            "password": null,
            "persist_config": null,
            "pod": "sample-0",
            "proxy": "http://basicauth.proxy.local:8080",
            "proxy_headers": {
                "basic_auth": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                "proxy_basic_auth": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                "user_agent": null
            },
            "username": null,
            "validate_certs": null
        }
    },
    "msg": "Failed to execute on pod sample-0 due to : (0)\nReason: failed CONNECT via proxy status: 407\n"
ISSUE TYPE
  • Bug Report
COMPONENT NAME
  • k8s_cp
  • k8s_exec
  • ... (not sure)
ANSIBLE VERSION
ansible [core 2.11.5]
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.9/dist-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.9.2 (default, Feb 28 2021, 17:03:44) [GCC 10.2.1 20210110]
  jinja version = 3.0.1
  libyaml = True
COLLECTION VERSION
# /root/.ansible/collections/ansible_collections
Collection      Version
--------------- -------
cloud.common    2.0.4
kubernetes.core 2.2.0

# pip list
kubernetes         18.20.0
CONFIGURATION
(empty)
OS / ENVIRONMENT

debian 11 (bullseye)

STEPS TO REPRODUCE
  1. setup http proxy server requiring basic authentication.
  2. deploy pod from behind http proxy (any official image is ok)
  3. k8s_exec (command: 'date') or k8s_cp (upload or download text file) from behind above http proxy.

Following are my test codes.
ansible-playbook -i hosts -e test=alpine:latest

- name: bootstrap ansible test
  hosts: localhost
  gather_facts: no
  connection: local
  tasks:
   - ...
---
- name: setup
  block:
  - set_fact:
      images: [ "alpine:latest",  "debian:bullseye" ]
      kubeconfig: "/root/.kube/config"
      cases: "{{ [] }}"
  - set_fact:
      cases: |
        {{ cases + [{  'image': item , 'container': item|replace(':','-')|replace('/','-')|replace('.','')  }] }}
    with_items: "{{ images }}"
    
  - template:
      src: "pod-template.j2"
      dest: "/tmp/pod-sample.yaml"
  - k8s:
      state: present
      src: "/tmp/pod-sample.yaml"
      kubeconfig: "{{ kubeconfig }}"

  - name: wait pod ready (this doesn't work in some cases...)
    command: |
       kubectl wait pod --for=condition=ready --kubeconfig {{kubeconfig}} sample-0 --timeout=150s

  - name: prepare content
    copy:
      dest: "/tmp/{{item}}.sh"
      content: |
         #!/bin/sh
         echo "{{item}}" > /tmp/{{item}}.txt
         date            >> /tmp/{{item}}.txt
      mode: +x
    with_items: "{{ cases | map(attribute='container')| list }}"

- name: "test : {{ test }}"
  set_fact:
    target: "{{ test |replace(':','-')|replace('/','-')| replace('.','') }}"

- name: test  {{ target }}
  block:
    - include_tasks: "k8s.yaml"
      vars:
        container: "{{ target }}"
        namespace:  "default"
        pod:        "sample-0"
        shell:      "/bin/sh -c"
        exec: |
           rm -f /tmp/{{target}}.txt
           date > /tmp/{{target}}.txt
        download: { 'remote_path': "/tmp/{{target}}.txt", 'local_path': "/tmp/{{target}}1.txt" }
    - include_tasks: "k8s.yaml"
      vars:
        container: "{{ target }}"
        namespace:  "default"
        pod:        "sample-0"
        shell:      "/bin/sh -c"
        upload: { 'local_path': "/tmp/{{target}}.sh", 'remote_path':"/tmp/{{target}}1.sh" }
        exec: |
           rm -f /tmp/{{target}}.txt
           /tmp/{{target}}1.sh
        download: { 'remote_path': "/tmp/{{target}}.txt", 'local_path': "/tmp/{{target}}1.txt" }
    - debug:
        msg: "got: {{ lookup('file', '/tmp/{{target}}1.txt') }}"

---
# k8s.yaml
- name: get environment variables from current shell for proxy
  set_fact:
    localenv: "{{  localenv|default({}) | combine ({ item : (lookup('env', item)| default('')) }) }}"
  with_items:
    - https_proxy
    - no_proxy
    - K8S_AUTH_PROXY
    - K8S_AUTH_PROXY_HEADERS_BASIC_AUTH
    - K8S_AUTH_PROXY_HEADERS_PROXY_BASIC_AUTH

- debug:
   var: localenv

- name: "uploading     x       core.k8s_cp"
  when: upload is defined
  kubernetes.core.k8s_cp:
     state:         to_pod
     kubeconfig:    "{{ kubeconfig }}"
     namespace:     "{{ namespace }}"
     pod:           "{{ pod }}"
     container:     "{{ container }}"
     local_path:    "{{ upload.local_path }}"
     remote_path:   "{{ upload.remote_path }}"
     proxy: "{{ localenv.K8S_AUTH_PROXY }}"
     proxy_headers:
       basic_auth: "{{ localenv.K8S_AUTH_PROXY_HEADERS_BASIC_AUTH }}"
       proxy_basic_auth: "{{ localenv.K8S_AUTH_PROXY_HEADERS_PROXY_BASIC_AUTH }}"

- name: "exec          x       core.k8s_exec"
  when: exec is defined
  kubernetes.core.k8s_exec:
     kubeconfig:   "{{ kubeconfig }}"
     namespace:    "{{ namespace }}"
     pod:          "{{ pod }}"
     container:    "{{ container }}"
     command: >-
        {{shell}} '{{ exec }}'
     proxy: "{{ localenv.K8S_AUTH_PROXY }}"
     proxy_headers:
       basic_auth: "{{ localenv.K8S_AUTH_PROXY_HEADERS_BASIC_AUTH }}"
       proxy_basic_auth: "{{ localenv.K8S_AUTH_PROXY_HEADERS_PROXY_BASIC_AUTH }}"
  register: result

- name: "result of remote exection"
  debug:
    var: result

- name: "downloading   x       core.k8s_cp"
  when: download is defined
  kubernetes.core.k8s_cp:
     state: from_pod
     kubeconfig:   "{{ kubeconfig }}"
     namespace:    "{{ namespace }}"
     pod:          "{{ pod }}"
     container:    "{{ container }}"
     remote_path:  "{{ download.remote_path }}"
     local_path:   "{{ download.local_path }}"
     proxy: "{{ localenv.K8S_AUTH_PROXY }}"
     proxy_headers:
       basic_auth: "{{ localenv.K8S_AUTH_PROXY_HEADERS_BASIC_AUTH }}"
       proxy_basic_auth: "{{ localenv.K8S_AUTH_PROXY_HEADERS_PROXY_BASIC_AUTH }}"
---
# pod-template.j2
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: "sample"
  namespace: "default"
spec:
  selector:
    matchLabels:
      k8s-app: "sample"
  serviceName: "sample"
  replicas: 1
  template:
    metadata:
      labels:
        k8s-app: "sample"
    spec:
      containers:
{% for node in cases %}
      - name: {{ node.container }}
        image: {{ node.image }}
        imagePullPolicy: IfNotPresent
        command:
          - sh
          - "-c"
          - |
            tail -f /dev/null
{% endfor %}
EXPECTED RESULTS

as it described in docs, both of k8s_cp and k8s_exec can work with http proxy authentication.

ACTUAL RESULTS

both k8s_cp and k8s_exec failed when http proxy requires authentication.


Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions