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

Basic HTTP authentication scheme not working with injected secret #65

Closed
bjartekh opened this issue Oct 24, 2024 · 3 comments
Closed

Basic HTTP authentication scheme not working with injected secret #65

bjartekh opened this issue Oct 24, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@bjartekh
Copy link

What happened?

I get "invalid header" from provider-http when adding my basicAuth token (from a kubernetes secret) to the Authorization header in the DisposableRequest.

Basic auth requires a base64-encoded user+secret. So when I add my secret as a kubernetes secret I'm base64-encoding it twice. (a kubernetes secret must be added as base64, and will be decoded when read).

But I get "invalid header" when I do this in a DisposableRequest.
I have verified that my request is sent if I only base64 it once, but in those instances it sends the username:password in cleartext and I get a HTTP 401 from the 3rdparty API.

From the provider-http I see the following in the logs (after base64-encoding twice).

  Warning  CannotCreateExternalResource  5s    managed/disposablerequest.http.crossplane.io  failed to send http request: (ommitted url). : net/http: invalid header field value for "Authorization"

How can we reproduce it?

Create a kubernetes secret called "my-secret-external". This contains a user+password for calling a 3rd-party API which requires Basic authentication.

Base64-encode the username+password, and then base64 the result again (so when it is injected into the DisposableRequest as Authorization header, it will still be base64 encoded as required in the specification).

To reproduce:

  1. echo "username:password" | base64

Result: dXNlcm5hbWU6cGFzc3dvcmQK

  1. echo dXNlcm5hbWU6cGFzc3dvcmQK | base64

Result: ZFhObGNtNWhiV1U2Y0dGemMzZHZjbVFLCg==

Then apply this as a secret into kubernetes.

apiVersion: v1
kind: Secret
metadata:
  name: my-secret-external
  namespace: crossplane-system
type: Opaque
data:
  authorization: ZFhObGNtNWhiV1U2Y0dGemMzZHZjbVFLCg==

In my crossplane composition I reference the secret in the Authorization header like this:
(and according to the docs)

   Authorization:
                - "Basic {{ my-secret-external:crossplane-system:authorization }}"

More complete example:

  - name: http-request
      base: 
        apiVersion: http.crossplane.io/v1alpha2
        kind: DisposableRequest
        spec:
          providerConfigRef:
            name: http-test-config
          deletionPolicy: Orphan
          forProvider:
            body: |
              {
               .... ommited
              }
            expectedResponse: .body.state == "success"
            headers:
              Authorization:
                - "Basic {{ my-secret-external:crossplane-system:authorization }}"
              Content-Type:
                - application/json
            insecureSkipTLSVerify: true
            method: POST
            rollbackRetriesLimit: 1
            url: https://3rdpartyapiexample.com/api/pipeline/start
            waitTimeout: 5m
...ommitted...			

What environment did it happen in?

Crossplane version:
v1.16.0

xpkg.upbound.io/crossplane-contrib/provider-http:v1.0.5

  • Cloud provider or hardware configuration: Azure
  • Kubernetes version (use kubectl version): 1.28.9
  • Kubernetes distribution (e.g. Tectonic, GKE, OpenShift): AKS
@bjartekh bjartekh added the bug Something isn't working label Oct 24, 2024
@arielsepton
Copy link
Member

arielsepton commented Oct 24, 2024

Thanks for bringing this up!

Here are two potential solutions:

  1. Check if a newline character is being added:
    When base64 encoding without the -n flag, a newline character might get added. You can avoid this by using:

    echo -n "username:password" | base64
    echo -n <base64-credentials> | base64
  2. Try encoding directly in YAML if double base64 encoding is the issue:
    You can perform the second base64 encoding directly in the request using jq, which avoids manually encoding it twice. Here's an example:

    Authorization:
      - ("Basic " + ( "{{ my-secret-external:crossplane-system:authorization }}" | @base64 ))

Let me know if this helps!

@arielsepton
Copy link
Member

I’ll close this as it’s not a bug. If you still encounter issues, feel free to reopen or add a comment. Thanks!

@bjartekh
Copy link
Author

Thx for your reply, I was able to make it work using

echo -n "base64encodedusername+password" | base64 -w 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants