Fixed some more rbac issues, v2022.03.15

This commit is contained in:
斟酌 鵬兄 2022-03-15 01:39:12 +09:00
parent c2272e3816
commit 4fe54aabf0
5 changed files with 140 additions and 50 deletions

View File

@ -1,54 +1,59 @@
# ACME webhook example
# Introduction
First, [RTFM](https://cert-manager.io/docs/configuration/acme/dns01/).
The ACME issuer type supports an optional 'webhook' solver, which can be used
to implement custom DNS01 challenge solving logic.
Have you read it? If you haven't go read it. Cuz I'll keep everything short.
This is useful if you need to use cert-manager with a DNS provider that is not
officially supported in cert-manager core.
This is a dns01 solver for [FreeDNS](https://freedns.afraid.org/).
## Why not in core?
As the project & adoption has grown, there has been an influx of DNS provider
pull requests to our core codebase. As this number has grown, the test matrix
has become un-maintainable and so, it's not possible for us to certify that
providers work to a sufficient level.
By creating this 'interface' between cert-manager and DNS providers, we allow
users to quickly iterate and test out new integrations, and then packaging
those up themselves as 'extensions' to cert-manager.
We can also then provide a standardised 'testing framework', or set of
conformance tests, which allow us to validate the a DNS provider works as
expected.
## Creating your own webhook
Webhook's themselves are deployed as Kubernetes API services, in order to allow
administrators to restrict access to webhooks with Kubernetes RBAC.
This is important, as otherwise it'd be possible for anyone with access to your
webhook to complete ACME challenge validations and obtain certificates.
To make the set up of these webhook's easier, we provide a template repository
that can be used to get started quickly.
### Creating your own repository
### Running the test suite
All DNS providers **must** run the DNS01 provider conformance testing suite,
else they will have undetermined behaviour when used with cert-manager.
**It is essential that you configure and run the test suite when creating a
DNS01 webhook.**
An example Go test file has been provided in [main_test.go](https://github.com/jetstack/cert-manager-webhook-example/blob/master/main_test.go).
You can run the test suite with:
Pull requests welcome. I'm completely unfamiliar with golang. I did it by looking at
other webhook repos and this is the result.
## Install
```bash
$ TEST_ZONE_NAME=example.com. make test
$ cd deploy
$ helm show values freedns-webhook > my-values.yaml
$ edit my-values.yaml
$ helm install -n cert-manager [INSTALLATION_NAME] freedns-webhook/ -f my-values.yaml
```
The example file has a number of areas you must fill in and replace with your
own options in order for tests to pass.
## ClusterIssuer for Let's encrypt staging
```yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
email: myemail@example.com
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: le-staging
solvers:
- dns01:
webhook:
groupName: acme.freedns.afraid.org
solverName: freedns-solver
config:
secretName: freedns-auth
```
## FreeDNS webhook settings
Normally if you haven't changed anything, the default namespace should be
`cert-manager`. It should be within the same namespace for the webhook when
you do `helm install webhook -n cert-manager`.
```yaml
apiVersion: v1
kind: Secret
metadata:
name: freedns-auth
namespace: cert-manager
data:
username: [YOUR_USERNAME_IN_BASE64]
password: [YOUR_PASSWORD_IN_BASE64]
type: Opaque
```
Additionally, the following names can be customized
* acme.freedns.afraid.org
* freedns-auth

View File

@ -8,6 +8,45 @@ metadata:
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "freedns-webhook.fullname" . }}:secret-read
namespace: {{ .Release.Namespace }}
labels:
app: {{ include "freedns-webhook.name" . }}
chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
rules:
- apiGroups:
- ''
resources:
- 'secrets'
verbs:
- 'get'
---
# Grant the webhook permission to read the secret
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "freedns-webhook.fullname" . }}:secret-read
namespace: {{ .Release.Namespace }}
labels:
app: {{ include "freedns-webhook.name" . }}
chart: {{ include "freedns-webhook.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "freedns-webhook.fullname" . }}:secret-read
subjects:
- apiGroup: ""
kind: ServiceAccount
name: {{ include "freedns-webhook.fullname" . }}
namespace: {{ .Release.Namespace }}
---
# Grant the webhook permission to read the ConfigMap containing the Kubernetes
# apiserver's requestheader-ca-certificate.
# This ConfigMap is automatically created by the Kubernetes apiserver.

View File

@ -14,7 +14,7 @@ certManager:
image:
repository: penguinade/cert-manager-webhook-freedns
tag: latest
tag: 2022.03.15
pullPolicy: IfNotPresent
nameOverride: ""

View File

@ -24,6 +24,7 @@ type FreeDNSOperations interface {
type FreeDNS struct {
AuthCookie *http.Cookie
DomainId string
LoggedOut bool
}
const URI_LOGIN = "https://freedns.afraid.org/zc.php?step=2"
@ -73,6 +74,8 @@ func _HttpRequest(method string, url string, PostData url.Values, ExCookie *http
return nil, "", err
}
req.Header.Set("User-Agent", "github.com/tgckpg/cert-manager-webhook-freedns (2022.03.15)")
if ExCookie != nil {
req.AddCookie(ExCookie)
}
@ -112,6 +115,7 @@ func (dnsObj *FreeDNS) Login(Username string, Password string) error {
for _, cookie := range resp.Cookies() {
if cookie.Name == "dns_cookie" {
dnsObj.AuthCookie = cookie
dnsObj.LoggedOut = false
}
}
@ -119,7 +123,7 @@ func (dnsObj *FreeDNS) Login(Username string, Password string) error {
}
func (dnsObj *FreeDNS) Logout() error {
if dnsObj.AuthCookie == nil {
if dnsObj.LoggedOut {
return nil
}
@ -128,7 +132,7 @@ func (dnsObj *FreeDNS) Logout() error {
return err
}
dnsObj.AuthCookie = nil
dnsObj.LoggedOut = true
return nil
}

42
freedns/freedns_test.go Executable file
View File

@ -0,0 +1,42 @@
package freedns
import (
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
/*
func TestHttpRequest(t *testing.T) {
_HttpRequest("GET", "http://127.0.0.1:12345", nil, nil)
}
*/
func TestGetDomainFromZone(t *testing.T) {
assert.Equal(t, GetDomainFromZone("a.b.example.com"), "example.com")
assert.Equal(t, GetDomainFromZone("example.com"), "example.com")
}
func TestOperations(t *testing.T) {
freeDNS := FreeDNS{}
var UserName = os.Getenv("FREEDNS_USERNAME")
var Password = os.Getenv("FREEDNS_PASSWORD")
var SelectedDomain = os.Getenv("FREEDNS_DOMAIN")
require.NotEmpty(t, UserName, "Please set the env vars for FREEDNS_USERNAME")
require.NotEmpty(t, Password, "Please set the env vars for FREEDNS_PASSWORD")
require.NotEmpty(t, SelectedDomain, "Please set the env vars for FREEDNS_DOMAIN")
require.Nil(t, freeDNS.Login(UserName, Password))
require.Nil(t, freeDNS.SelectDomain(SelectedDomain))
require.Nil(t, freeDNS.AddRecord("TXT", "", "\"TEST\"", false, ""))
id, _ := freeDNS.FindRecord(SelectedDomain, "TXT", "\"TEST\"")
require.NotEmpty(t, id)
require.Nil(t, freeDNS.DeleteRecord(id))
require.Nil(t, freeDNS.Logout())
require.Equal(t, freeDNS.LoggedOut, true)
}