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

Feat/ldap certificate connexion #92

Merged
merged 2 commits into from
Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/h44z/wg-portal)
[![Docker Pulls](https://img.shields.io/docker/pulls/h44z/wg-portal.svg)](https://hub.docker.com/r/h44z/wg-portal/)

A simple, web based configuration portal for [WireGuard](https://wireguard.com).
The portal uses the WireGuard [wgctrl](https://github.com/WireGuard/wgctrl-go) library to manage existing VPN
interfaces. This allows for seamless activation or deactivation of new users, without disturbing existing VPN
A simple, web based configuration portal for [WireGuard](https://wireguard.com).
The portal uses the WireGuard [wgctrl](https://github.com/WireGuard/wgctrl-go) library to manage existing VPN
interfaces. This allows for seamless activation or deactivation of new users, without disturbing existing VPN
connections.

The configuration portal currently supports using SQLite and MySQL as a user source for authentication and profile data.
Expand All @@ -31,11 +31,11 @@ It also supports LDAP (Active Directory or OpenLDAP) as authentication provider.
* Can be used with existing WireGuard setups
* Support for multiple WireGuard interfaces
* REST API for management and client deployment

![Screenshot](screenshot.png)

## Setup
Make sure that your host system has at least one WireGuard interface (for example wg0) available.
Make sure that your host system has at least one WireGuard interface (for example wg0) available.
If you did not start up a WireGuard interface yet, take a look at [wg-quick](https://manpages.debian.org/unstable/wireguard-tools/wg-quick.8.en.html) in order to get started.

### Docker
Expand Down Expand Up @@ -156,6 +156,9 @@ The following configuration options are available:
| LDAP_ATTR_LASTNAME | attrLastname | ldap | sn | User lastname attribute. |
| LDAP_ATTR_PHONE | attrPhone | ldap | telephoneNumber | User phone number attribute. |
| LDAP_ATTR_GROUPS | attrGroups | ldap | memberOf | User groups attribute. |
| LDAP_CERT_CONN | ldapCertConn | ldap | false | Allow connection with certificate against LDAP server without user/password |
| LDAPTLS_CERT | ldapTlsCert | ldap | | The LDAP cert's path |
| LDAPTLS_KEY | ldapTlsKey | ldap | | The LDAP key's path |
| LOG_LEVEL | | | debug | Specify log level, one of: trace, debug, info, off. |
| LOG_JSON | | | false | Format log output as JSON. |
| LOG_COLOR | | | true | Colorize log output. |
Expand Down Expand Up @@ -190,7 +193,7 @@ email:
user: test@gmail.com
pass: topsecret
wg:
devices:
devices:
- wg0
- wg1
defaultDevice: wg0
Expand All @@ -199,8 +202,8 @@ wg:
```

### RESTful API
WireGuard Portal offers a RESTful API to interact with.
The API is documented using OpenAPI 2.0, the Swagger UI can be found
WireGuard Portal offers a RESTful API to interact with.
The API is documented using OpenAPI 2.0, the Swagger UI can be found
under the URL `http://<your wg-portal ip/domain>/swagger/index.html?displayOperationId=true`.

The [API's unittesting](tests/test_API.py) may serve as an example how to make use of the API with python3 & pyswagger.
Expand All @@ -210,7 +213,7 @@ The [API's unittesting](tests/test_API.py) may serve as an example how to make u
* Generation or application of any `iptables` or `nftables` rules.
* Setting up or changing IP-addresses of the WireGuard interface on operating systems other than linux.
* Importing private keys of an existing WireGuard setup.

## Application stack

* [Gin, HTTP web framework written in Go](https://github.com/gin-gonic/gin)
Expand All @@ -221,6 +224,6 @@ The [API's unittesting](tests/test_API.py) may serve as an example how to make u
## License

* MIT License. [MIT](LICENSE.txt) or https://opensource.org/licenses/MIT


This project was inspired by [wg-gen-web](https://github.com/vx3r/wg-gen-web).
29 changes: 28 additions & 1 deletion internal/authentication/providers/ldap/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ldap

import (
"crypto/tls"
"io/ioutil"
"strings"

"github.com/gin-gonic/gin"
Expand Down Expand Up @@ -154,7 +155,33 @@ func (provider Provider) GetUserModel(ctx *authentication.AuthContext) (*authent
}

func (provider Provider) open() (*ldap.Conn, error) {
tlsConfig := &tls.Config{InsecureSkipVerify: !provider.config.CertValidation}
var tlsConfig *tls.Config

if provider.config.LdapCertConn {

cert_plain, err := ioutil.ReadFile(provider.config.LdapTlsCert)
if err != nil {
return nil, errors.WithMessage(err, "failed to load the certificate")

}

key, err := ioutil.ReadFile(provider.config.LdapTlsKey)
if err != nil {
return nil, errors.WithMessage(err, "failed to load the key")
}

cert_x509, err := tls.X509KeyPair(cert_plain, key)
if err != nil {
return nil, errors.WithMessage(err, "failed X509")

}
tlsConfig = &tls.Config{Certificates: []tls.Certificate{cert_x509}}

} else {

tlsConfig = &tls.Config{InsecureSkipVerify: !provider.config.CertValidation}
}

conn, err := ldap.DialURL(provider.config.URL, ldap.DialWithTLSConfig(tlsConfig))
if err != nil {
return nil, errors.WithMessage(err, "failed to connect to LDAP")
Expand Down
10 changes: 6 additions & 4 deletions internal/ldap/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
gldap "github.com/go-ldap/ldap/v3"
)


type Type string

const (
Expand All @@ -26,8 +25,11 @@ type Config struct {
PhoneAttribute string `yaml:"attrPhone" envconfig:"LDAP_ATTR_PHONE"`
GroupMemberAttribute string `yaml:"attrGroups" envconfig:"LDAP_ATTR_GROUPS"`

LoginFilter string `yaml:"loginFilter" envconfig:"LDAP_LOGIN_FILTER"` // {{login_identifier}} gets replaced with the login email address
SyncFilter string `yaml:"syncFilter" envconfig:"LDAP_SYNC_FILTER"`
AdminLdapGroup string `yaml:"adminGroup" envconfig:"LDAP_ADMIN_GROUP"` // Members of this group receive admin rights in WG-Portal
LoginFilter string `yaml:"loginFilter" envconfig:"LDAP_LOGIN_FILTER"` // {{login_identifier}} gets replaced with the login email address
SyncFilter string `yaml:"syncFilter" envconfig:"LDAP_SYNC_FILTER"`
AdminLdapGroup string `yaml:"adminGroup" envconfig:"LDAP_ADMIN_GROUP"` // Members of this group receive admin rights in WG-Portal
AdminLdapGroup_ *gldap.DN `yaml:"-"`
LdapCertConn bool `yaml:"ldapCertConn" envconfig:"LDAP_CERT_CONN"`
LdapTlsCert string `yaml:"ldapTlsCert" envconfig:"LDAPTLS_CERT"`
LdapTlsKey string `yaml:"ldapTlsKey" envconfig:"LDAPTLS_KEY"`
}
29 changes: 28 additions & 1 deletion internal/ldap/ldap.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ldap

import (
"crypto/tls"
"io/ioutil"

"github.com/go-ldap/ldap/v3"
"github.com/pkg/errors"
Expand All @@ -14,7 +15,33 @@ type RawLdapData struct {
}

func Open(cfg *Config) (*ldap.Conn, error) {
tlsConfig := &tls.Config{InsecureSkipVerify: !cfg.CertValidation}
var tlsConfig *tls.Config

if cfg.LdapCertConn {

cert_plain, err := ioutil.ReadFile(cfg.LdapTlsCert)
if err != nil {
return nil, errors.WithMessage(err, "failed to load the certificate")

}

key, err := ioutil.ReadFile(cfg.LdapTlsKey)
if err != nil {
return nil, errors.WithMessage(err, "failed to load the key")
}

cert_x509, err := tls.X509KeyPair(cert_plain, key)
if err != nil {
return nil, errors.WithMessage(err, "failed X509")

}
tlsConfig = &tls.Config{Certificates: []tls.Certificate{cert_x509}}

} else {

tlsConfig = &tls.Config{InsecureSkipVerify: !cfg.CertValidation}
}

conn, err := ldap.DialURL(cfg.URL, ldap.DialWithTLSConfig(tlsConfig))
if err != nil {
return nil, errors.Wrap(err, "failed to connect to LDAP")
Expand Down