feat(ccd): support IP conflict validation in Kubernetes Secret mode (#384)

Signed-off-by: Paramoshka <parfenov_ivan_42a@mail.ru>
This commit is contained in:
Parfenov Ivan 2025-07-23 14:21:07 +03:00 committed by GitHub
parent fbee2c07dc
commit e5bf819db3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 61 additions and 12 deletions

View File

@ -329,10 +329,10 @@ func (openVPNPKI *OpenVPNPKI) easyrsaBuildClient(commonName string) (err error)
secretMetaData := metav1.ObjectMeta{
Name: fmt.Sprintf(secretClientTmpl, clientCert.SerialNumber),
Labels: map[string]string{
"index.txt": "",
"type": "clientAuth",
"name": commonName,
"app.kubernetes.io/managed-by": "ovpn-admin",
labelKeyIndexTxt: "",
labelKeyType: labelValueClientAuth,
labelKeyName: commonName,
labelKeyManagedBy: labelValueManagedByApp,
},
Annotations: map[string]string{
"commonName": commonName,

65
main.go
View File

@ -35,14 +35,21 @@ import (
)
const (
usernameRegexp = `^([a-zA-Z0-9_.\-@])+$`
passwordMinLength = 6
certsArchiveFileName = "certs.tar.gz"
ccdArchiveFileName = "ccd.tar.gz"
indexTxtDateLayout = "060102150405Z"
stringDateFormat = "2006-01-02 15:04:05"
downloadCertsApiUrl = "api/data/certs/download"
downloadCcdApiUrl = "api/data/ccd/download"
usernameRegexp = `^([a-zA-Z0-9_.\-@])+$`
passwordMinLength = 6
certsArchiveFileName = "certs.tar.gz"
ccdArchiveFileName = "ccd.tar.gz"
indexTxtDateLayout = "060102150405Z"
stringDateFormat = "2006-01-02 15:04:05"
downloadCertsApiUrl = "api/data/certs/download"
downloadCcdApiUrl = "api/data/ccd/download"
labelKeyIndexTxt = "index.txt"
labelKeyType = "type"
labelKeyName = "name"
labelKeyManagedBy = "app.kubernetes.io/managed-by"
labelValueClientAuth = "clientAuth"
labelValueManagedByApp = "ovpn-admin"
prefixStaticRoute = "ifconfig-push"
kubeNamespaceFilePath = "/var/run/secrets/kubernetes.io/serviceaccount/namespace"
)
@ -861,11 +868,53 @@ func (oAdmin *OvpnAdmin) getCcd(username string) Ccd {
}
func checkStaticAddressIsFree(staticAddress string, username string) bool {
if *storageBackend == "kubernetes.secrets" {
log.Infof("Static address: %s", staticAddress)
labelSelector := fmt.Sprintf("%s=%s,%s=%s",
labelKeyType, labelValueClientAuth,
labelKeyManagedBy, labelValueManagedByApp)
secrets, err := app.secretsGetByLabels(labelSelector)
if err != nil {
log.Error(err)
}
for _, secret := range secrets.Items {
otherUser := secret.Labels["name"]
if otherUser == username {
continue
}
dataCCD, ok := secret.Data["ccd"]
if !ok {
continue
}
lines := strings.Split(string(dataCCD), "\n")
for _, line := range lines {
if strings.HasPrefix(line, prefixStaticRoute) {
fields := strings.Fields(line)
if len(fields) >= 2 && fields[1] == staticAddress {
log.Warnf("IP %s already assigned to user %s", staticAddress, otherUser)
return false
}
}
}
}
return true
}
o := runBash(fmt.Sprintf("grep -rl ' %[1]s ' %[2]s | grep -vx %[2]s/%[3]s | wc -l", staticAddress, *ccdDir, username))
if strings.TrimSpace(o) == "0" {
return true
}
return false
}