cyberark / conjur-api-go

Go client for the CyberArk Conjur API
Apache License 2.0
20 stars 20 forks source link

Error with certificates trying to retrieve a secret #176

Closed R3DRUN3 closed 7 months ago

R3DRUN3 commented 1 year ago

Summary

When I try to retrieve a secret, I get the following error: x509: certificate is not standards compliant.

I noticed it may be related to this issue however, even trying from ubuntu, I get a certificate error, albeit a different one: x509: certificate signed by unknown authority.

Steps to Reproduce

The following is the Go script that I am using:

package main

import (
    "fmt"
    "os"

    "github.com/cyberark/conjur-api-go/conjurapi"
    "github.com/cyberark/conjur-api-go/conjurapi/authn"
)

func main() {
    variableIdentifier := "secrets/TEST-VARIABLE-TEKTON-PIPELINE"

    config, err := conjurapi.LoadConfig()
    if err != nil {
        panic(err)
    }

    conjur, err := conjurapi.NewClientFromKey(config,
        authn.LoginPair{
            Login:  os.Getenv("CONJUR_AUTHN_LOGIN"),
            APIKey: os.Getenv("CONJUR_AUTHN_API_KEY"),
        },
    )
    if err != nil {
        panic(err)
    }

    // Retrieve a secret into []byte.
    secretValue, err := conjur.RetrieveSecret(variableIdentifier)
    if err != nil {
        panic(err)
    }
    fmt.Println("The secret value is: ", string(secretValue))

    // Retrieve a secret into io.ReadCloser, then read into []byte.
    // Alternatively, you can transfer the secret directly into secure memory,
    // vault, keychain, etc.
    secretResponse, err := conjur.RetrieveSecretReader(variableIdentifier)
    if err != nil {
        panic(err)
    }

    secretValue, err = conjurapi.ReadResponseBody(secretResponse)
    if err != nil {
        panic(err)
    }
    fmt.Println("The secret value is: ", string(secretValue))
}

Expected Results

The program complete the secret retrieval without errors.

Actual Results

See the above errors.

Reproducible

Version/Tag number

go version: go1.20.4 darwin/amd64 library version: github.com/cyberark/conjur-api-go v0.11.0

Environment setup

The script is launched from localhost and the Conjur instance is on a remote VM (connection via VPN).

Additional Information

I get the same error with the terraform conjur provider. The config env vars are ok: I've succesfully run a bash script with the same values and it works.

It seems that the problem is related to self signed certificates, is there a way to bypass this check? Thank you.

R3DRUN3 commented 1 year ago

NOTE I was able to bypass this problem by specifying the full certificate chain instead of just the Conjur host certificate, this also solved the problems that I was having with terraform-provider-conjur (based upon this Go library).

I don't know if this behavior is intentional, it seems a little strange having to specify the entire certificate chain bundle... In fact, it seems strange and a bit unconventional having to specify a public SSL certificate at all 🤔

The same problem occurred (and was bypassed) in the same way in the conjur-puppet module as well (see this issue).

szh commented 1 year ago

Hi @R3DRUN3,

Are you using a self-signed certificate? Can you please post the values of your loaded config?

R3DRUN3 commented 1 year ago

Hi @szh, yes it is a self signed certificate:

-----BEGIN CERTIFICATE-----
MIID0DCCArigAwIBAgIUeO2/+zmaBjmfJRxB1bwzM93lnmAwDQYJKoZIhvcNAQEL
BQAwUTEQMA4GA1UECgwHZGVmYXVsdDESMBAGA1UECwwJQ29uanVyIENBMSkwJwYD
VQQDDCBjb25qdXItbGIudnNwaGVyZS5wbGF5Z3JvdW5kLmNvbTAeFw0yMzAxMTAx
MTI3MzRaFw0zMzAxMDcxMTI3MzRaMCsxKTAnBgNVBAMMIGNvbmp1ci1sYi52c3Bo
ZXJlLnBsYXlncm91bmQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAvP11Ad8F8rVQXGrvhqv4yBhCLW+E85KnNV9TjNiV0fojrQMNHTIWwY5TL8vL
kTohi6NTHPZCBu6ig1sAwlvwF72oHrjDITN7YUxUcgCAuQzEG4lK2cPNWkmsMlaZ
e9ECJguvIh1QF+TW+72CIESR9IQeQKuPwZis7VBqbInQboiYHb849xVWIpzdQH2D
4IGhknuZQCUUOYbtpp1aJOJnQvEwFZ2hwzlK2i63JA18SafPHxt91r4TC9Jih3wN
CriL/TtFaz9/n0CQM1HETpt3B00aRom6QI6dnqixACJ2fuNqyiqnn53c7HiLWCvQ
/vJ46CTGxOKeae+sBeDjGrjTkQIDAQABo4HFMIHCMA4GA1UdDwEB/wQEAwIFoDAd
BgNVHQ4EFgQU2jmj7l5rSw0yVb/vlWAYkK/YBwkwgZAGA1UdEQSBiDCBhYIgY29u
anVyLWxiLnZzcGhlcmUucGxheWdyb3VuZC5jb22CH2Nvbmp1ci0xLnZzcGhlcmUu
cGxheWdyb3VuZC5jb22CH2Nvbmp1ci0yLnZzcGhlcmUucGxheWdyb3VuZC5jb22C
H2Nvbmp1ci0zLnZzcGhlcmUucGxheWdyb3VuZC5jb20wDQYJKoZIhvcNAQELBQAD
ggEBADjwsbz7BG641cWjokup7b4MT6Q1ts8cbKg3rFRH8IP2p3KA0amzDvnGXehF
RJ83rj9wXdPBpxfzRCvkqw8u4et1fXZ7XyirrqBZh0eQWu5ix/Sd9NdOE8DLw+Xz
wAsaGp7NgpBK3gs3k5iX38yk0Gstk3Y7fjzqUmRSeJ9EOs3Wpe+hxfkurS9HDAMy
M0iVnZDvEsRLeGYELa685Ga6/lSBXshMbmLDISF0M3LqgNYDCJZPJLYY5pf6XDfv
Wt4QUEbBrpX11OMBRyRYZW3Nf7LIaNGxzitTbNdCpJqjwyJV2J9eX3VFtrVaPczs
TmwipMTS+WBhDto0a6pZ74J5shU=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEFzCCAv+gAwIBAgIJAL5lp9Ol3u6KMA0GCSqGSIb3DQEBCwUAMFExEDAOBgNV
BAoMB2RlZmF1bHQxEjAQBgNVBAsMCUNvbmp1ciBDQTEpMCcGA1UEAwwgY29uanVy
LWxiLnZzcGhlcmUucGxheWdyb3VuZC5jb20wHhcNMjMwMTEwMTEyNzI4WhcNMzMw
MTA3MTEyNzI4WjBRMRAwDgYDVQQKDAdkZWZhdWx0MRIwEAYDVQQLDAlDb25qdXIg
Q0ExKTAnBgNVBAMMIGNvbmp1ci1sYi52c3BoZXJlLnBsYXlncm91bmQuY29tMIIB
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3W5RgNlzqFS76Nvo4++0AC7I
nHXHXdi8tINf1BWSoKVkT9rtzG4yTa/yJZUkS1GEagoeuiciRUi5GvU1jJAMgxHy
wlb5/fMBZSNGpDaqg2xTVQC98flvNCW8zrqAq40OhvaR5wqkoEo9nL1jMHd4X3Oq
ZOvLNFbLaWVsEI0eBG00nB+71ykorZllbBQp2BLM+eLYQEvpZRXsQB8rsWOavI2y
jkwcRp9ZreoZ/FMcbfxE+vkclI8g5egag2NQd1eYznXvJtG44OhgReqzpeIZ/sYd
1u9sUPqOiEg1Wktfwp4/FrRvKBTzLvLNQ0fQrlKwPxu8tH0kxgTSbYl4EKo78wID
AQABo4HxMIHuMIGQBgNVHREEgYgwgYWCIGNvbmp1ci1sYi52c3BoZXJlLnBsYXln
cm91bmQuY29tgh9jb25qdXItMS52c3BoZXJlLnBsYXlncm91bmQuY29tgh9jb25q
dXItMi52c3BoZXJlLnBsYXlncm91bmQuY29tgh9jb25qdXItMy52c3BoZXJlLnBs
YXlncm91bmQuY29tMB0GA1UdDgQWBBRIYp17facC6wS8ZgHvrraX9oOmrDAfBgNV
HSMEGDAWgBRIYp17facC6wS8ZgHvrraX9oOmrDAMBgNVHRMEBTADAQH/MAsGA1Ud
DwQEAwIB5jANBgkqhkiG9w0BAQsFAAOCAQEASnn8uqBALs8Lo52PU/ANHgH95bKc
fO9ejmeW7iQrPXXW0GMdisJQJUdRpptmC9tQiAvOP51Qa3kIhVkFky9/VD9EepwS
jnJ+87W1/nGx2RyQQsOnjomd2RZe9sftrL3kpdK/e4tOoxpJl/w2lz8WTzqupBew
ZBocoP91IcmLAu9nPOtWY7mEFvWWR8ZVcQIeWbZymJqqv2HBs07u12mcfRLP9KK+
sb/HlYxV8TBF3LtrFUEIfk4OaFJEI7iHqh3Dnpu+6NR/f96nf/uuDOhJk8KQ11Rd
U+1yG164iUDUNMofkO2n2/URlm9ytAIENrzG7A+k2RWqlhdb0yApTlR2VQ==
-----END CERTIFICATE-----

I saved this in a file called conjur and then I launch the Go script via a bash script:

#!/bin/bash

export CONJUR_APPLIANCE_URL="https://10.7.0.122"
export CONJUR_ACCOUNT="default"
export CONJUR_AUTHN_LOGIN="host/conjur/tekton-pipeline-demo"
export CONJUR_AUTHN_API_KEY="<conjur-api-key-here>"
export CONJUR_CERT_FILE="conjur"

go run main.go
doodlesbykumbi commented 1 year ago

I'll take some time tomorrow to try to reproduce

doodlesbykumbi commented 1 year ago

I haven't been able to reproduce this yet

doodlesbykumbi commented 1 year ago

Please try validating the connection by running a curl command against the same CONJUR_APPLIANCE_URL

R3DRUN3 commented 1 year ago

@doodlesbykumbi already done it. this is the bash script I am using and it works:

#!/bin/bash

echo "Retrieving secret from Conjur..."
TOKEN=$(curl -s --insecure -X POST --header "Accept-Encoding: base64" --data <API-KEY-HERE> https://10.7.0.122/authn/default/host%2Fconjur%2Ftekton-pipeline-demo/authenticate)
SECRET=$(curl -s --insecure -H "Authorization: Token token=\"$TOKEN\"" https://10.7.0.120/secrets/default/variable/secrets%2FTEST-VARIABLE-TEKTON-PIPELINE)
echo "The secret value is: $SECRET"
doodlesbykumbi commented 1 year ago

Let's try and isolate this issue from conjur-api-go and see if it shows upon the HTTP client @R3DRUN3.

Try replace your main.go with this one. Run it with all the same configuration

// main.go
package main

import (
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "log"
    "net/http"
    "net/http/httputil"
    "time"

    "github.com/cyberark/conjur-api-go/conjurapi"
)

func main() {
    config, err := conjurapi.LoadConfig()
    if err != nil {
        log.Fatal(err)
    }
    cert, err := config.ReadSSLCert()
    if err != nil {
        log.Fatal(err)
    }
    httpClient, err := newHTTPSClient(cert)
    if err != nil {
        log.Fatal(err)
    }
    if err != nil {
        // Handle error
        fmt.Println("Error creating HTTP client:", err)
        return
    }

    resp, err := httpClient.Get(config.ApplianceURL)
    if err != nil {
        // Handle error
        fmt.Println("Error making GET request:", err)
        return
    }
    defer resp.Body.Close()

    dump, err := httputil.DumpResponse(resp, true)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%s", dump)

    // Process the response
    // ...
}

func newHTTPSClient(cert []byte) (*http.Client, error) {
    pool := x509.NewCertPool()
    ok := pool.AppendCertsFromPEM(cert)
    if !ok {
        return nil, fmt.Errorf("Can't append Conjur SSL cert")
    }

    tr := &http.Transport{
        TLSClientConfig: &tls.Config{RootCAs: pool},
    }
    return &http.Client{Transport: tr, Timeout: time.Second * 10}, nil
}
R3DRUN3 commented 1 year ago

I will close this issue as I am able to bypass the problem specifying the certificate chain. My suggestion to you is to add a flag to bypass certificate validation (for testing purpose).

doodlesbykumbi commented 1 year ago

Hey @R3DRUN3. Thanks for closing the issue but I would appreciate if you can test out the code from the previous comment. It would help us to figure out if the issue is related to code we wrote or if its present on the Go HTTP client.