Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for headers to requests #207

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Both are identical multi-arch images built for `amd64`, `arm64`, `arm/v7`, `ppc6
- Values can also be base64 encoded URLs that download binary data e.g. executables
- The key in the `ConfigMap`/`Secret` must end with "`.url`" ([see](https://github.com/kiwigrid/k8s-sidecar/blob/master/test/resources/resources.yaml#L84))

# Usage
# Usage

Example for a simple deployment can be found in [`example.yaml`](./example.yaml). Depending on the cluster setup you have to grant yourself admin rights first:
```shell
Expand Down Expand Up @@ -77,6 +77,7 @@ If the filename ends with `.url` suffix, the content will be processed as a URL
| `REQ_USERNAME` | Username to use for basic authentication for requests to `REQ_URL` and for `*.url` triggered requests | false | - | string |
| `REQ_PASSWORD` | Password to use for basic authentication for requests to `REQ_URL` and for `*.url` triggered requests | false | - | string |
| `REQ_BASIC_AUTH_ENCODING` | Which encoding to use for username and password as [by default it's undefined](https://datatracker.ietf.org/doc/html/rfc7617) (e.g. `utf-8`). | false | `latin1` | string |
| `REQ_HEADERS` | Headers for use for request to `REQ_URL` and for `*.url` triggered request (ex. `{"x-apikey": "token"}`) | `` | - | string |
| `SCRIPT` | Absolute path to shell script to execute after a configmap got reloaded. It runs before calls to `REQ_URI` | false | - | string |
| `ERROR_THROTTLE_SLEEP` | How many seconds to wait before watching resources again when an error occurs | false | `5` | integer |
| `SKIP_TLS_VERIFY` | Set to `true` to skip tls verification for kube api calls | false | - | boolean |
Expand Down
6 changes: 4 additions & 2 deletions src/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import hashlib
import os
import subprocess
import json
from datetime import datetime

import requests
Expand All @@ -22,6 +23,7 @@
REQ_RETRY_BACKOFF_FACTOR = 1.1 if os.getenv("REQ_RETRY_BACKOFF_FACTOR") is None else float(
os.getenv("REQ_RETRY_BACKOFF_FACTOR"))
REQ_TIMEOUT = 10 if os.getenv("REQ_TIMEOUT") is None else float(os.getenv("REQ_TIMEOUT"))
REQ_HEADERS = {} if os.getenv("REQ_HEADERS") is None else json.loads(os.getenv("REQ_HEADERS"))

# Tune default timeouts as outlined in
# https://github.com/kubernetes-client/python/issues/1148#issuecomment-626184613
Expand Down Expand Up @@ -127,9 +129,9 @@ def request(url, method, enable_5xx=False, payload=None):

# If method is not provided use GET as default
if method == "GET" or not method:
res = r.get("%s" % url, auth=auth, timeout=REQ_TIMEOUT)
res = r.get("%s" % url, auth=auth, headers=REQ_HEADERS, timeout=REQ_TIMEOUT)
elif method == "POST":
res = r.post("%s" % url, auth=auth, json=payload, timeout=REQ_TIMEOUT)
res = r.post("%s" % url, auth=auth, headers=REQ_HEADERS, json=payload, timeout=REQ_TIMEOUT)
else:
logger.warning(f"Invalid REQ_METHOD: '{method}', please use 'GET' or 'POST'. Doing nothing.")
return
Expand Down
9 changes: 9 additions & 0 deletions test/resources/resources.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,12 @@ metadata:
binaryData:
# Base64 encoded url is 'http://dummy-server/static/kubelogo.png'
url-downloaded-kubelogo.png.url: "aHR0cDovL2R1bW15LXNlcnZlci9zdGF0aWMva3ViZWxvZ28ucG5n"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: url-configmap-headers
labels:
findme: "yup"
data:
secured.url: "http://dummy-server/secured-token"
48 changes: 40 additions & 8 deletions test/resources/sidecar.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,10 @@ spec:
value: both
- name: SCRIPT
value: "/opt/script.sh"
- name: REQ_USERNAME
value: "user1"
- name: REQ_PASSWORD
value: "abcdefghijklmnopqrstuvwxyz"
- 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: REQ_URL
value: "http://dummy-server/secure-token"
- name: REQ_HEADERS
value: '{"x-apitoken": "test"}'
- name: LOG_LEVEL
value: "DEBUG"
volumes:
Expand Down Expand Up @@ -117,6 +114,41 @@ spec:
---
apiVersion: v1
kind: Pod
metadata:
name: sidecar-headers
namespace: default
spec:
serviceAccountName: sample-acc
containers:
- name: sidecar
image: kiwigrid/k8s-sidecar:testing
volumeMounts:
- 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: LOG_LEVEL
value: "DEBUG"
volumes:
- name: shared-volume
emptyDir: {}
- name: script-volume
configMap:
name: script-configmap
defaultMode: 0777
---
apiVersion: v1
kind: Pod
metadata:
name: dummy-server-pod
namespace: default
Expand All @@ -140,4 +172,4 @@ spec:
ports:
- port: 80
targetPort: 80
name: http
name: http
10 changes: 8 additions & 2 deletions test/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from fastapi.logger import logger
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi.staticfiles import StaticFiles
from starlette.responses import PlainTextResponse
from starlette.responses import PlainTextResponse, JSONResponse

app = FastAPI()

Expand Down Expand Up @@ -45,4 +45,10 @@ async def read_secure_data(auth: HTTPBasicCredentials = Depends(basic_auth_schem
detail=f"Incorrect user (${auth.username}) or password (${auth.password})",
headers={"WWW-Authenticate": "Basic"},
)
return 'allowed'
return 'allowed'

@app.get("/secured-token")
async def read_secure_header(x_apitoken: str | None = Header(default=None)):
if x_apitoken is None:
return 400
return 200