问题描述
provider,err := oidc.NewProvider(ctx,providerURI)
if err != nil {
log.Println(err)
}
虽然使用相同的提供者URI在本地运行 ,但它有效, 我能够成功获得提供者!
我使用完全相同的提供程序URL (作为env
变量)将其部署到K8S,并使用port-forwarding
调试,
但是,在k8S中出现错误,没有得到provider
。
错误是:
2020/08/14 16:42:22 Get "https://ace.svar.com/.well-kNown/openid-configuration": x509: certificate signed by unkNown authority
我已将证书添加到映像并验证,部署后我exec
进入了k8s容器,并且在server.crt
下看到了/usr/local/share/ca-certificates/
文件路径。
仍然有相同的错误,如果我在这里想念其他的话,任何想法... 不知道它是否真的与OIDC库或更一般的内容有关。
FROM golang:1.14.7 AS builder
RUN go get github.com/go-delve/delve/cmd/dlv
ADD server.crt /usr/local/share/ca-certificates/server.crt
RUN chmod 644 /usr/local/share/ca-certificates/server.crt && update-ca-certificates
RUN mkdir /app
ADD . /app
workdir /app
RUN CGO_ENABLED=0 GOOS=linux go build -gcflags="all=-N -l" -o main ./...
FROM debian:buster AS production
copY --from=builder /app .
copY --from=builder /go/bin/dlv /
copY --from=builder /usr/local/share/ca-certificates/ /usr/local/share/ca-certificates/
EXPOSE 8000 40000
ENV SSL_CERT_DIR=/usr/local/share/ca-certificates/
ENV PORT=8000
CMD ["/dlv","--listen=:40000","--headless=true","--api-version=2","--accept-multiclient","exec","./main"]
我从GO-OIDC
存储库的作者那里重放来尝试使用
https://godoc.org/github.com/coreos/go-oidc#ClientContext
不确定如何,有什么想法吗?
解决方法
在oidc.ClientContext文档中,它显示了如何传递自定义http.Client
:
myClient := &http.Client{}
ctx := oidc.ClientContext(parentContext,myClient)
// This will use the custom client
provider,err := oidc.NewProvider(ctx,"https://accounts.example.com")
提供自定义http.Client
允许自定义TLS处理。
TLS配置
要使用特定的CA信任文件创建http.Client
,请使用以下帮助器功能:
func tlsConf(trustfile string) (t *tls.Config,err error) {
if trustfile == "" {
// DON'T USE IN PRODUCTION (but handy for testing)
t = &tls.Config{InsecureSkipVerify: true}
return
}
pembody,err := ioutil.ReadFile(trustfile)
if err != nil {
err = fmt.Errorf("failed to load trust file %q: %w",trustfile,err)
return
}
rootCAs := x509.NewCertPool()
if ok := rootCAs.AppendCertsFromPEM(pembody); !ok {
err = fmt.Errorf("invalid PEM file %q",trustfile)
return
}
t = &tls.Config{RootCAs: rootCAs}
return
}
和:
func httpCli(trustfile string) (hc *http.Client,err error) {
tc,err := tlsConf(trustfile)
if err != nil {
return
}
hc = &http.Client{Transport: &http.Transport{TLSClientConfig: tc}}
return
}
因此要将以上内容与OIDC软件包一起使用以进行快速测试:
hc,err := httpCli("") // DON'T USE IN PRODUCTION - will trust any TLS cert
ctx := oidc.ClientContext(parentContext,hc)
provider,"https://accounts.example.com")
如果这可行,则将正确的信任文件添加到您的应用中:
hc,err := httpCli("/usr/local/share/ca-certificates/server.crt"))
CA Trust
如果您的server.crt
信任文件不起作用,则可能列出了错误的主题/颁发者。
要确定,您可以从任何远程服务器(端口443是默认的https端口)grab the trust cert(和可选的签名链):
echo | openssl s_client -connect ace.svar.com:443 -showcerts 2> /dev/null > ace.txt
由于我不知道您的基础架构是什么样子,因此我将使用google.com:443
的示例输出:
---
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=*.google.com
i:/C=US/O=Google Trust Services/CN=GTS CA 1O1
-----BEGIN CERTIFICATE-----
MIIKIzCCCQugAwIBAgIQF9rkH7fB/M4IAAAAAE2d0TANBgkqhkiG9w0BAQsFADBC
MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMRMw
...
-----END CERTIFICATE-----
s:
表示证书的主题-您可以看到服务器名称由通配符CN=*.google.com
标识。如果您在ace.txt
中看到类似内容,则您的server.crt
应该包含以下几行(从BEGIN CERTIFICATE
开始,以END CERTIFICATE
结尾)。
您可能还会注意到,i:
行表示发行方证书名称。如果它与s:
相同,则它是自签名证书,您就可以完成。
在google.com:443
示例中,主题(s:
)与颁发者(i:
)不同。因此,与其信任主题证书,不如信任发行者证书,而是可以信任多个服务器。由于主题证书由该发行者签名,因此信任链已完成。
Golang标准ssl库正在以下目录中寻找证书:https://github.com/golang/go/blob/master/src/crypto/x509/root_unix.go#L18-L37 && https://github.com/golang/go/blob/master/src/crypto/x509/root_linux.go#L8-L15,如果要在新位置中查找证书,则可以使用环境变量:{{1} }或SSL_CERT_FILE
并设置证书的位置。
因此,您的情况应该是:
SSL_CERT_DIR
,然后运行您的应用程序。