diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml index 1cae399..993a8ff 100644 --- a/.github/workflows/build_and_test.yaml +++ b/.github/workflows/build_and_test.yaml @@ -92,6 +92,7 @@ jobs: kubectl get pods wait_for_pod_ready "sidecar" + wait_for_pod_ready "sidecar-basicauth-args" wait_for_pod_ready "sidecar-5xx" wait_for_pod_ready "sidecar-pythonscript" wait_for_pod_ready "sidecar-pythonscript-logfile" @@ -108,7 +109,7 @@ jobs: sleep 20 echo "Installing resources..." kubectl apply -f "test/resources/resources.yaml" - pods=("sidecar" "sidecar-5xx" "sidecar-pythonscript" "sidecar-pythonscript-logfile") + pods=("sidecar" "sidecar-basicauth-args" "sidecar-5xx" "sidecar-pythonscript" "sidecar-pythonscript-logfile") resources=("sample-configmap" "sample-secret-binary" "absolute-configmap" "relative-configmap" "change-dir-configmap" "similar-configmap-secret" "url-configmap-500" "url-configmap-basic-auth" "sample-configmap") for p in ${pods[*]}; do for r in ${resources[*]}; do @@ -121,6 +122,7 @@ jobs: run: | mkdir /tmp/logs kubectl logs sidecar > /tmp/logs/sidecar.log + kubectl logs sidecar-basicauth-args > /tmp/logs/sidecar-basicauth-args.log kubectl logs sidecar-5xx > /tmp/logs/sidecar-5xx.log kubectl logs sidecar-pythonscript > /tmp/logs/sidecar-pythonscript.log kubectl logs sidecar-pythonscript-logfile > /tmp/logs/sidecar-pythonscript-logfile.log @@ -149,7 +151,10 @@ jobs: kubectl cp sidecar:/tmp/secured.txt /tmp/sidecar/secured.txt kubectl cp sidecar:/tmp/similar-configmap.txt /tmp/sidecar/similar-configmap.txt kubectl cp sidecar:/tmp/similar-secret.txt /tmp/sidecar/similar-secret.txt - + + echo "Downloading resource files from sidecar-basicauth-args pod" + kubectl cp sidecar-basicauth-args:/tmp/secured.txt /tmp/sidecar-basicauth-args/secured.txt + echo "Downloading resource files from sidecar-5xx..." kubectl cp sidecar-5xx:/tmp-5xx/hello.world /tmp/sidecar-5xx/hello.world kubectl cp sidecar-5xx:/tmp-5xx/cm-kubelogo.png /tmp/sidecar-5xx/cm-kubelogo.png @@ -205,6 +210,9 @@ jobs: echo -n "allowed" | diff - /tmp/sidecar/secured.txt && [ ! -f /tmp/sidecar/500.txt ] && echo "No 5xx file created" && ls /tmp/sidecar/script_result + - name: Verify sidecar-basicauth-args pod file after initial sync + run: | + echo -n "allowed" | diff - /tmp/sidecar-basicauth-args/secured.txt - name: Verify sidecar-5xx files after initial sync run: | echo -n '{"detail":"Not authenticated"}' | diff - /tmp/sidecar-5xx/secured.txt && diff --git a/README.md b/README.md index d4f4fae..e97b659 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,12 @@ metadata: If the filename ends with `.url` suffix, the content will be processed as a URL which the target file contents will be downloaded from. +## Configuration CLI Flags +| name | description | required | default | type | +|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|---------|---------| +| `--req-username-file` | Path to file containing username to use for basic authentication for requests to `REQ_URL` and for `*.url` triggered requests. This overrides the `REQ_USERNAME` | false | - | string | +| `--req-password-file` | Path to file containing password to use for basic authentication for requests to `REQ_URL` and for `*.url` triggered requests. This overrides the `REQ_PASSWORD` | false | - | string | + ## Configuration Environment Variables | name | description | required | default | type | diff --git a/src/helpers.py b/src/helpers.py index e282963..6114ae1 100755 --- a/src/helpers.py +++ b/src/helpers.py @@ -13,6 +13,12 @@ from requests.packages.urllib3.util.retry import Retry from logger import get_logger +import argparse + +parser = argparse.ArgumentParser(description="CLI flags for kiwigrid sidecar") +parser.add_argument("--req-username-file", type=str, metavar=argparse.REMAINDER, help="path to file containing basic-auth username for REQ. This takes precedence over the environment variable REQ_USERNAME") +parser.add_argument("--req-password-file", type=str, metavar=argparse.REMAINDER, help="path to file containing basic-auth password for REQ. This takes precedence over the environment variable REQ_PASSWORD") +args = parser.parse_args() CONTENT_TYPE_TEXT = "ascii" CONTENT_TYPE_BASE64_BINARY = "binary" @@ -110,11 +116,36 @@ def remove_file(folder, filename): return False -def request(url, method, enable_5xx=False, payload=None): - enforce_status_codes = list() if enable_5xx else [500, 502, 503, 504] - +def read_file_content(file_path): + try: + with open(file_path, 'r') as file: + return file.read().strip() + except FileNotFoundError: + logger.warning(f"File not found at: {file_path}") + except PermissionError: + logger.error(f"No read permission for file: {file_path}") + except Exception as e: + logger.error(f"An unexpected error occurred: {e}") + return None + + +def fetch_basic_auth_credentials(): username = os.getenv("REQ_USERNAME") password = os.getenv("REQ_PASSWORD") + if args.req_username_file: + username_from_file = read_file_content(args.req_username_file) + if username_from_file is not None: + username = username_from_file + if args.req_password_file: + password_from_file = read_file_content(args.req_password_file) + if password_from_file is not None: + password = password_from_file + return username, password + + +def request(url, method, enable_5xx=False, payload=None): + enforce_status_codes = list() if enable_5xx else [500, 502, 503, 504] + username,password = fetch_basic_auth_credentials() encoding = 'latin1' if not os.getenv("REQ_BASIC_AUTH_ENCODING") else os.getenv("REQ_BASIC_AUTH_ENCODING") if username and password: auth = HTTPBasicAuth(username.encode(encoding), password.encode(encoding)) diff --git a/src/requirements.txt b/src/requirements.txt index ace6d92..f099508 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -1,4 +1,5 @@ kubernetes==29.0.0 requests==2.31.0 python-json-logger==2.0.7 -logfmter==0.0.7 \ No newline at end of file +logfmter==0.0.7 +argparse==1.4.0 diff --git a/test/resources/sidecar.yaml b/test/resources/sidecar.yaml index 0d76c16..40ca9c4 100644 --- a/test/resources/sidecar.yaml +++ b/test/resources/sidecar.yaml @@ -335,3 +335,57 @@ spec: - port: 80 targetPort: 80 name: http +--- +apiVersion: v1 +kind: Pod +metadata: + name: sidecar-basicauth-args + namespace: default +spec: + serviceAccountName: sample-acc + containers: + - name: sidecar + image: kiwigrid/k8s-sidecar:testing + command: [ "python" , "-u" , "sidecar.py" , "--req-username-file=/opt/creds/username" , "--req-password-file=/opt/creds/password"] + imagePullPolicy: IfNotPresent + volumeMounts: + - name: auth-creds + mountPath: /opt/creds/ + - name: shared-volume + mountPath: /tmp/ + - name: script-volume + mountPath: /opt/script.sh + subPath: script.sh + env: + - name: LABEL + value: "findme" + - name: FOLDER + value: /tmp/ + - name: RESOURCE + value: both + - name: SCRIPT + value: "/opt/script.sh" + - name: REQ_BASIC_AUTH_ENCODING + # the python server we're using for the tests expects ascii encoding of basic auth credentials, hence we can't use non-ascii characters in the password or username + value: "ascii" + - name: LOG_LEVEL + value: "DEBUG" + volumes: + - name: auth-creds + secret: + secretName: dummyyserver-credentials + - name: shared-volume + emptyDir: {} + - name: script-volume + configMap: + name: script-configmap + defaultMode: 0777 +--- +apiVersion: v1 +kind: Secret +metadata: + name: dummyyserver-credentials +type: Opaque +stringData: + username: "user1" + password: "abcdefghijklmnopqrstuvwxyz" \ No newline at end of file