fix passw auth; refactor type auth
This commit is contained in:
parent
efc44d1e5f
commit
c168f36862
11 changed files with 106 additions and 63 deletions
|
@ -12,7 +12,7 @@ var (
|
||||||
userIsNotActiveError = errors.New("user is not active")
|
userIsNotActiveError = errors.New("user is not active")
|
||||||
passwordMismatchedError = errors.New("password mismatched")
|
passwordMismatchedError = errors.New("password mismatched")
|
||||||
tokenMismatchedError = errors.New("token mismatched")
|
tokenMismatchedError = errors.New("token mismatched")
|
||||||
checkAppError = errors.New("failed to check 2FA app")
|
checkAppError = errors.New("failed to check 2FA TOTP app")
|
||||||
registerAppError = errors.New("failed to register 2FA app")
|
registerAppError = errors.New("failed to register 2FA TOTP app")
|
||||||
authBackendDisabled = errors.New("auth backend not enabled yet")
|
authBackendDisabled = errors.New("auth backend not enabled yet")
|
||||||
)
|
)
|
||||||
|
|
|
@ -36,8 +36,7 @@ var (
|
||||||
clientConfigTemplatePath = kingpin.Flag("templates.clientconfig-path", "path to custom client.conf.tpl").Default("").Envar("OVPN_TEMPLATES_CC_PATH").String()
|
clientConfigTemplatePath = kingpin.Flag("templates.clientconfig-path", "path to custom client.conf.tpl").Default("").Envar("OVPN_TEMPLATES_CC_PATH").String()
|
||||||
ccdTemplatePath = kingpin.Flag("templates.ccd-path", "path to custom ccd.tpl").Default("").Envar("OVPN_TEMPLATES_CCD_PATH").String()
|
ccdTemplatePath = kingpin.Flag("templates.ccd-path", "path to custom ccd.tpl").Default("").Envar("OVPN_TEMPLATES_CCD_PATH").String()
|
||||||
|
|
||||||
AuthByPassword = kingpin.Flag("auth.password", "enable additional password authentication").Default("false").Envar("OVPN_AUTH").Bool()
|
AuthType = kingpin.Flag("auth.type", "auth type").Default("").Envar("OVPN_AUTH").HintOptions("TOTP", "PASSWORD", "").String()
|
||||||
AuthTFA = kingpin.Flag("auth.2fa", "auth type").Default("false").Envar("OVPN_AUTH_TFA").Bool()
|
|
||||||
AuthDatabase = kingpin.Flag("auth.db", "database path for password authentication").Default("./easyrsa/pki/users.db").Envar("OVPN_AUTH_DB_PATH").String()
|
AuthDatabase = kingpin.Flag("auth.db", "database path for password authentication").Default("./easyrsa/pki/users.db").Envar("OVPN_AUTH_DB_PATH").String()
|
||||||
|
|
||||||
LogLevel = kingpin.Flag("log.level", "set log level: trace, debug, info, warn, error (default info)").Default("info").Envar("LOG_LEVEL").String()
|
LogLevel = kingpin.Flag("log.level", "set log level: trace, debug, info, warn, error (default info)").Default("info").Envar("LOG_LEVEL").String()
|
||||||
|
|
|
@ -74,7 +74,7 @@ func (oAdmin *OvpnAdmin) UserResetTFAHandler(w http.ResponseWriter, r *http.Requ
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
} else {
|
} else {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
fmt.Fprintf(w, "2FA reseted")
|
fmt.Fprintf(w, "TOTP reseted")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ func (oAdmin *OvpnAdmin) UserUnrevokeHandler(w http.ResponseWriter, r *http.Requ
|
||||||
func (oAdmin *OvpnAdmin) UserChangePasswordHandler(w http.ResponseWriter, r *http.Request) {
|
func (oAdmin *OvpnAdmin) UserChangePasswordHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Info(r.RemoteAddr, " ", r.RequestURI)
|
log.Info(r.RemoteAddr, " ", r.RequestURI)
|
||||||
_ = r.ParseForm()
|
_ = r.ParseForm()
|
||||||
if *AuthByPassword {
|
if oAdmin.ExtraAuth {
|
||||||
err, msg := oAdmin.userChangePassword(r.FormValue("username"), r.FormValue("password"))
|
err, msg := oAdmin.userChangePassword(r.FormValue("username"), r.FormValue("password"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
|
|
@ -152,7 +152,7 @@ func (oAdmin *OvpnAdmin) renderClientConfig(username string) string {
|
||||||
conf.Key = fRead(*EasyrsaDirPath + "/pki/private/" + username + ".key")
|
conf.Key = fRead(*EasyrsaDirPath + "/pki/private/" + username + ".key")
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.PasswdAuth = *AuthByPassword
|
conf.PasswdAuth = oAdmin.ExtraAuth
|
||||||
|
|
||||||
t := oAdmin.getTemplate("client.conf.tpl", "client-config", *clientConfigTemplatePath)
|
t := oAdmin.getTemplate("client.conf.tpl", "client-config", *clientConfigTemplatePath)
|
||||||
|
|
||||||
|
@ -313,8 +313,12 @@ func (oAdmin *OvpnAdmin) usersList() []OpenvpnClient {
|
||||||
connectedUniqUsers += 1
|
connectedUniqUsers += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if oAdmin.ExtraAuth{
|
||||||
if oAdmin.isSecondFactorConfigured(ovpnClient.Identity) {
|
if oAdmin.isSecondFactorConfigured(ovpnClient.Identity) {
|
||||||
ovpnClient.SecondFactor = true
|
ovpnClient.SecondFactor = "enabled"
|
||||||
|
} else {
|
||||||
|
ovpnClient.SecondFactor = "disabled"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
users = append(users, ovpnClient)
|
users = append(users, ovpnClient)
|
||||||
|
@ -354,7 +358,7 @@ func (oAdmin *OvpnAdmin) userCreate(username, password string) (string, error) {
|
||||||
return err.Error(), err
|
return err.Error(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
if *AuthByPassword {
|
if oAdmin.ExtraAuth {
|
||||||
if err := validatePassword(password); err != nil {
|
if err := validatePassword(password); err != nil {
|
||||||
log.Debugf("userCreate: authByPassword(): %s", err.Error())
|
log.Debugf("userCreate: authByPassword(): %s", err.Error())
|
||||||
return err.Error(), err
|
return err.Error(), err
|
||||||
|
@ -367,7 +371,7 @@ func (oAdmin *OvpnAdmin) userCreate(username, password string) (string, error) {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
return err.Error(), err
|
return err.Error(), err
|
||||||
}
|
}
|
||||||
if *AuthByPassword {
|
if oAdmin.ExtraAuth {
|
||||||
err = oAdmin.KubeClient.updatePasswordSecret(username, []byte(password))
|
err = oAdmin.KubeClient.updatePasswordSecret(username, []byte(password))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err.Error(), err
|
return err.Error(), err
|
||||||
|
@ -376,7 +380,7 @@ func (oAdmin *OvpnAdmin) userCreate(username, password string) (string, error) {
|
||||||
} else {
|
} else {
|
||||||
o := runBash(fmt.Sprintf("cd %s && easyrsa build-client-full %s nopass 1>/dev/null", *EasyrsaDirPath, username))
|
o := runBash(fmt.Sprintf("cd %s && easyrsa build-client-full %s nopass 1>/dev/null", *EasyrsaDirPath, username))
|
||||||
log.Debug(o)
|
log.Debug(o)
|
||||||
if *AuthByPassword {
|
if oAdmin.ExtraAuth {
|
||||||
_, err := oAdmin.OUser.CreateUser(username, password)
|
_, err := oAdmin.OUser.CreateUser(username, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err.Error(), err
|
return err.Error(), err
|
||||||
|
@ -435,14 +439,21 @@ func (oAdmin *OvpnAdmin) isSecondFactorConfigured(username string) bool {
|
||||||
}
|
}
|
||||||
return sfe
|
return sfe
|
||||||
case "filesystem":
|
case "filesystem":
|
||||||
|
switch *AuthType {
|
||||||
|
case "TOTP":
|
||||||
sfe, err := oAdmin.OUser.IsSecondFactorEnabled(username)
|
sfe, err := oAdmin.OUser.IsSecondFactorEnabled(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return sfe
|
return sfe
|
||||||
|
case "PASSWORD":
|
||||||
|
return true
|
||||||
|
//TODO: check if password is exist in db
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (oAdmin *OvpnAdmin) getUserSecret(username string) (string, error) {
|
func (oAdmin *OvpnAdmin) getUserSecret(username string) (string, error) {
|
||||||
|
@ -538,11 +549,11 @@ func (oAdmin *OvpnAdmin) registerUserAuthApp(username, totp string) error {
|
||||||
|
|
||||||
for i, u := range oAdmin.clients {
|
for i, u := range oAdmin.clients {
|
||||||
if u.Identity == username {
|
if u.Identity == username {
|
||||||
oAdmin.clients[i].SecondFactor = true
|
oAdmin.clients[i].SecondFactor = "enabled"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("2FA configured for user %s", username)
|
log.Infof("TOTP configured for user %s", username)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("user \"%s\" not found", username)
|
return fmt.Errorf("user \"%s\" not found", username)
|
||||||
|
@ -567,7 +578,7 @@ func (oAdmin *OvpnAdmin) resetUserAuthApp(username string) error {
|
||||||
|
|
||||||
for i, u := range oAdmin.clients {
|
for i, u := range oAdmin.clients {
|
||||||
if u.Identity == username {
|
if u.Identity == username {
|
||||||
oAdmin.clients[i].SecondFactor = false
|
oAdmin.clients[i].SecondFactor = "disabled"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -587,7 +598,12 @@ func (oAdmin *OvpnAdmin) checkAuth(username, token string) error {
|
||||||
return authErr
|
return authErr
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
switch *AuthType {
|
||||||
|
case "TOTP":
|
||||||
auth, authErr = oAdmin.OUser.AuthUser(username, "", token)
|
auth, authErr = oAdmin.OUser.AuthUser(username, "", token)
|
||||||
|
case "PASSWORD":
|
||||||
|
auth, authErr = oAdmin.OUser.AuthUser(username, token, "")
|
||||||
|
}
|
||||||
if authErr != nil {
|
if authErr != nil {
|
||||||
return authErr
|
return authErr
|
||||||
}
|
}
|
||||||
|
@ -625,7 +641,7 @@ func (oAdmin *OvpnAdmin) userRevoke(username string) (error, string) {
|
||||||
log.Debugln(o)
|
log.Debugln(o)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *AuthByPassword {
|
if oAdmin.ExtraAuth {
|
||||||
if oAdmin.OUser.CheckUserExistent(username) {
|
if oAdmin.OUser.CheckUserExistent(username) {
|
||||||
revokeMsg, revokeErr := oAdmin.OUser.RevokedUser(username)
|
revokeMsg, revokeErr := oAdmin.OUser.RevokedUser(username)
|
||||||
log.Debug(revokeMsg)
|
log.Debug(revokeMsg)
|
||||||
|
@ -693,7 +709,7 @@ func (oAdmin *OvpnAdmin) userUnrevoke(username string) (error, string) {
|
||||||
|
|
||||||
_ = runBash(fmt.Sprintf("cd %s && easyrsa gen-crl 1>/dev/null", *EasyrsaDirPath))
|
_ = runBash(fmt.Sprintf("cd %s && easyrsa gen-crl 1>/dev/null", *EasyrsaDirPath))
|
||||||
|
|
||||||
if *AuthByPassword {
|
if oAdmin.ExtraAuth {
|
||||||
if oAdmin.OUser.CheckUserExistent(username) {
|
if oAdmin.OUser.CheckUserExistent(username) {
|
||||||
restoreMsg, restoreErr := oAdmin.OUser.RestoreUser(username)
|
restoreMsg, restoreErr := oAdmin.OUser.RestoreUser(username)
|
||||||
log.Debug(restoreMsg)
|
log.Debug(restoreMsg)
|
||||||
|
@ -750,7 +766,7 @@ func (oAdmin *OvpnAdmin) userRotate(username, newPassword string) (error, string
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *AuthByPassword {
|
if oAdmin.ExtraAuth {
|
||||||
if oAdmin.OUser.CheckUserExistent(username) {
|
if oAdmin.OUser.CheckUserExistent(username) {
|
||||||
deleteMsg, deleteErr := oAdmin.OUser.DeleteUser(username, true)
|
deleteMsg, deleteErr := oAdmin.OUser.DeleteUser(username, true)
|
||||||
log.Debug(deleteMsg)
|
log.Debug(deleteMsg)
|
||||||
|
@ -819,7 +835,7 @@ func (oAdmin *OvpnAdmin) userDelete(username string) (error, string) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if *AuthByPassword {
|
if oAdmin.ExtraAuth {
|
||||||
if oAdmin.OUser.CheckUserExistent(username) {
|
if oAdmin.OUser.CheckUserExistent(username) {
|
||||||
deleteMsg, deleteErr := oAdmin.OUser.DeleteUser(username, true)
|
deleteMsg, deleteErr := oAdmin.OUser.DeleteUser(username, true)
|
||||||
log.Debug(deleteMsg)
|
log.Debug(deleteMsg)
|
||||||
|
@ -1095,3 +1111,17 @@ func (oAdmin *OvpnAdmin) SyncWithMaster() {
|
||||||
oAdmin.SyncDataFromMaster()
|
oAdmin.SyncDataFromMaster()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (oAdmin *OvpnAdmin) IsTotpAuth() bool {
|
||||||
|
if IsModuleEnabled("totpAuth", oAdmin.Modules) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (oAdmin *OvpnAdmin) IsPasswdAuth() bool {
|
||||||
|
if IsModuleEnabled("passwdAuth", oAdmin.Modules) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ type OvpnAdmin struct {
|
||||||
Modules []string
|
Modules []string
|
||||||
mgmtStatusTimeFormat string
|
mgmtStatusTimeFormat string
|
||||||
CreateUserMutex *sync.Mutex
|
CreateUserMutex *sync.Mutex
|
||||||
|
ExtraAuth bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type OpenvpnServer struct {
|
type OpenvpnServer struct {
|
||||||
|
@ -48,7 +49,7 @@ type OpenvpnClient struct {
|
||||||
RevocationDate string `json:"RevocationDate"`
|
RevocationDate string `json:"RevocationDate"`
|
||||||
ConnectionStatus string `json:"ConnectionStatus"`
|
ConnectionStatus string `json:"ConnectionStatus"`
|
||||||
Connections int `json:"Connections"`
|
Connections int `json:"Connections"`
|
||||||
SecondFactor bool `json:"SecondFactor"`
|
SecondFactor string `json:"SecondFactor,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ccdRoute struct {
|
type ccdRoute struct {
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
"database/sql"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -555,3 +556,20 @@ func randStr(strSize int, randType string) string {
|
||||||
}
|
}
|
||||||
return string(bytes)
|
return string(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OpenDB(path string) *sql.DB {
|
||||||
|
db, err := sql.Open("sqlite3", path)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsModuleEnabled(desiredModule string, listModules []string) bool {
|
||||||
|
for _, module := range listModules {
|
||||||
|
if module == desiredModule {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -160,6 +160,7 @@ new Vue({
|
||||||
label: 'Download config',
|
label: 'Download config',
|
||||||
class: 'btn-info',
|
class: 'btn-info',
|
||||||
showWhenStatus: 'Active',
|
showWhenStatus: 'Active',
|
||||||
|
Require2FA: "true",
|
||||||
showForServerRole: ['master', 'slave'],
|
showForServerRole: ['master', 'slave'],
|
||||||
showForModule: ["core"],
|
showForModule: ["core"],
|
||||||
},
|
},
|
||||||
|
@ -353,7 +354,7 @@ new Vue({
|
||||||
|
|
||||||
getUserTFAData: function(data) {
|
getUserTFAData: function(data) {
|
||||||
let _this = this;
|
let _this = this;
|
||||||
if (!_this.secondfactor) {
|
if (_this.secondfactor == 'disabled' ) {
|
||||||
axios.request(axios_cfg('api/user/2fa/secret', data, 'form'))
|
axios.request(axios_cfg('api/user/2fa/secret', data, 'form'))
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
_this.u.secret = response.data;
|
_this.u.secret = response.data;
|
||||||
|
@ -374,15 +375,15 @@ new Vue({
|
||||||
_this.u.modalActionStatus = 200;
|
_this.u.modalActionStatus = 200;
|
||||||
_this.u.modalRegister2faVisible = false;
|
_this.u.modalRegister2faVisible = false;
|
||||||
_this.getUserData();
|
_this.getUserData();
|
||||||
_this.secondfactor = true;
|
_this.secondfactor = "enabled";
|
||||||
_this.u.token = "";
|
_this.u.token = "";
|
||||||
_this.u.secret = "";
|
_this.u.secret = "";
|
||||||
_this.$notify({title: '2FA application registered for user ' + username, type: 'success'});
|
_this.$notify({title: 'TOTP application registered for user ' + username, type: 'success'});
|
||||||
})
|
})
|
||||||
.catch(function(error) {
|
.catch(function(error) {
|
||||||
_this.u.modalActionStatus = error.response.status;
|
_this.u.modalActionStatus = error.response.status;
|
||||||
_this.u.modalActionMessage = error.response.data.message;
|
_this.u.modalActionMessage = error.response.data.message;
|
||||||
_this.$notify({title: 'Register 2FA application for user ' + username + ' failed!', type: 'error'});
|
_this.$notify({title: 'Register TOTP application for user ' + username + ' failed!', type: 'error'});
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -396,15 +397,15 @@ new Vue({
|
||||||
axios.request(axios_cfg('api/user/2fa/reset', data, 'form'))
|
axios.request(axios_cfg('api/user/2fa/reset', data, 'form'))
|
||||||
.then(function(response) {
|
.then(function(response) {
|
||||||
_this.u.modalActionStatus = 200;
|
_this.u.modalActionStatus = 200;
|
||||||
_this.secondfactor = false;
|
_this.secondfactor = "disabled";
|
||||||
_this.getUserTFAData(data);
|
_this.getUserTFAData(data);
|
||||||
_this.getUserData();
|
_this.getUserData();
|
||||||
_this.$notify({title: '2FA application reset for user ' + username, type: 'success'});
|
_this.$notify({title: 'TOTP application reset for user ' + username, type: 'success'});
|
||||||
})
|
})
|
||||||
.catch(function(error) {
|
.catch(function(error) {
|
||||||
_this.u.modalActionStatus = error.response.status;
|
_this.u.modalActionStatus = error.response.status;
|
||||||
_this.u.modalActionMessage = error.response.data.message;
|
_this.u.modalActionMessage = error.response.data.message;
|
||||||
_this.$notify({title: 'Reset 2FA application for user ' + username + ' failed!', type: 'error'});
|
_this.$notify({title: 'Reset TOTP application for user ' + username + ' failed!', type: 'error'});
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,10 @@
|
||||||
@click.left.stop="rowActionFn"
|
@click.left.stop="rowActionFn"
|
||||||
v-for="action in actions"
|
v-for="action in actions"
|
||||||
v-bind:class="action.class"
|
v-bind:class="action.class"
|
||||||
v-if="action.showWhenStatus == props.row.AccountStatus && action.showForServerRole.includes(serverRole) && action.showForModule.some(p=> modulesEnabled.includes(p))">
|
v-if="action.showWhenStatus == props.row.AccountStatus &&
|
||||||
|
( props.row.SecondFactor != 'disabled' || !(action.Require2FA) ) &&
|
||||||
|
action.showForServerRole.includes(serverRole) &&
|
||||||
|
action.showForModule.some(p=> modulesEnabled.includes(p))">
|
||||||
{{ action.label }}
|
{{ action.label }}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
|
@ -51,7 +54,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<input type="text" class="form-control el-square modal-el-margin" placeholder="Username [_a-zA-Z0-9\.-]" v-model="u.newUserName">
|
<input type="text" class="form-control el-square modal-el-margin" placeholder="Username [_a-zA-Z0-9\.-]" v-model="u.newUserName">
|
||||||
<input type="password" class="form-control el-square modal-el-margin" minlength="6" autocomplete="off" placeholder="Password [_a-zA-Z0-9\.-]" v-model="u.newUserPassword" v-if="modulesEnabled.includes('passwdAuth')">
|
<input type="password" class="form-control el-square modal-el-margin" minlength="6" autocomplete="off" placeholder="Password [_a-zA-Z0-9\.-]" v-model="u.newUserPassword" v-if="modulesEnabled.includes('passwdAuth')||modulesEnabled.includes('totpAuth')">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-footer justify-content-center" v-if="u.modalActionMessage.length > 0">
|
<div class="modal-footer justify-content-center" v-if="u.modalActionMessage.length > 0">
|
||||||
|
@ -232,10 +235,10 @@
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
|
|
||||||
<div class="modal-header justify-content-center">
|
<div class="modal-header justify-content-center">
|
||||||
<h4>2FA</h4>
|
<h4>2FA TOTP</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-body justify-content-center" v-if="!secondfactor">
|
<div class="modal-body justify-content-center" v-if="secondfactor == 'disabled' ">
|
||||||
<div style="text-align: center">
|
<div style="text-align: center">
|
||||||
<vue-qr
|
<vue-qr
|
||||||
:text=u.twofaurl
|
:text=u.twofaurl
|
||||||
|
@ -262,8 +265,8 @@
|
||||||
<input type="text" class="form-control el-square modal-el-margin" minlength="6" autocomplete="off" placeholder="Pin Code" v-model="u.token">
|
<input type="text" class="form-control el-square modal-el-margin" minlength="6" autocomplete="off" placeholder="Pin Code" v-model="u.token">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-body justify-content-center" v-if="secondfactor">
|
<div class="modal-body justify-content-center" v-if="secondfactor == 'enabled' ">
|
||||||
<h4>2FA already configured for user: <strong>{{ username }}</strong></h4>
|
<h4>2FA with TOTP already configured for user: <strong>{{ username }}</strong></h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-footer justify-content-center" v-if="u.modalActionMessage.length > 0">
|
<div class="modal-footer justify-content-center" v-if="u.modalActionMessage.length > 0">
|
||||||
|
@ -273,8 +276,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-success el-square modal-el-margin" v-if="!secondfactor" v-on:click.stop="registerUser2faApp(username)">Register 2FA</button>
|
<button type="button" class="btn btn-success el-square modal-el-margin" v-if="secondfactor == 'disabled' " v-on:click.stop="registerUser2faApp(username)">Register 2FA TOTP</button>
|
||||||
<button type="button" class="btn btn-danger el-square modal-el-margin" v-if="secondfactor" v-on:click.stop="resetUser2faApp(username)">Reset 2FA</button>
|
<button type="button" class="btn btn-danger el-square modal-el-margin" v-if="secondfactor == 'enabled' " v-on:click.stop="resetUser2faApp(username)">Reset 2FA TOTP</button>
|
||||||
<button type="button" class="btn btn-primary el-square d-flex justify-content-sm-end modal-el-margin" v-on:click.stop="u.modalActionMessage='';u.modalRegister2faVisible=false;u.token=''">Close</button>
|
<button type="button" class="btn btn-primary el-square d-flex justify-content-sm-end modal-el-margin" v-on:click.stop="u.modalActionMessage='';u.modalRegister2faVisible=false;u.token=''">Close</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
33
main.go
33
main.go
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"embed"
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
@ -85,24 +84,17 @@ func main() {
|
||||||
|
|
||||||
ovpnAdmin.Modules = append(ovpnAdmin.Modules, "core")
|
ovpnAdmin.Modules = append(ovpnAdmin.Modules, "core")
|
||||||
|
|
||||||
if *backend.AuthByPassword {
|
switch *backend.AuthType {
|
||||||
db, err := sql.Open("sqlite3", *backend.AuthDatabase)
|
case "TOTP":
|
||||||
if err != nil {
|
ovpnAdmin.ExtraAuth = true
|
||||||
kingpin.Fatalf(err.Error())
|
ovpnAdmin.OUser.Database = backend.OpenDB(*backend.AuthDatabase)
|
||||||
}
|
defer ovpnAdmin.OUser.Database.Close()
|
||||||
defer func(db *sql.DB) {
|
|
||||||
err = db.Close()
|
|
||||||
if err != nil {
|
|
||||||
kingpin.Fatalf(err.Error())
|
|
||||||
}
|
|
||||||
}(db)
|
|
||||||
ovpnAdmin.OUser.Database = db
|
|
||||||
|
|
||||||
ovpnAdmin.Modules = append(ovpnAdmin.Modules, "passwdAuth")
|
|
||||||
|
|
||||||
if *backend.AuthTFA {
|
|
||||||
ovpnAdmin.Modules = append(ovpnAdmin.Modules, "totpAuth")
|
ovpnAdmin.Modules = append(ovpnAdmin.Modules, "totpAuth")
|
||||||
}
|
case "PASSWORD":
|
||||||
|
ovpnAdmin.ExtraAuth = true
|
||||||
|
ovpnAdmin.OUser.Database = backend.OpenDB(*backend.AuthDatabase)
|
||||||
|
defer ovpnAdmin.OUser.Database.Close()
|
||||||
|
ovpnAdmin.Modules = append(ovpnAdmin.Modules, "passwdAuth")
|
||||||
}
|
}
|
||||||
|
|
||||||
if *backend.CcdEnabled {
|
if *backend.CcdEnabled {
|
||||||
|
@ -152,11 +144,10 @@ func main() {
|
||||||
http.HandleFunc("/api/user/ccd/apply", ovpnAdmin.UserApplyCcdHandler)
|
http.HandleFunc("/api/user/ccd/apply", ovpnAdmin.UserApplyCcdHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *backend.AuthByPassword {
|
if ovpnAdmin.ExtraAuth {
|
||||||
http.HandleFunc("/api/user/change-password", ovpnAdmin.UserChangePasswordHandler)
|
http.HandleFunc("/api/user/change-password", ovpnAdmin.UserChangePasswordHandler)
|
||||||
http.HandleFunc("/api/auth/check", ovpnAdmin.AuthCheckHandler)
|
http.HandleFunc("/api/auth/check", ovpnAdmin.AuthCheckHandler)
|
||||||
|
if *backend.AuthType == "TOTP" {
|
||||||
if *backend.AuthTFA {
|
|
||||||
http.HandleFunc("/api/user/2fa/secret", ovpnAdmin.UserGetSecretHandler)
|
http.HandleFunc("/api/user/2fa/secret", ovpnAdmin.UserGetSecretHandler)
|
||||||
http.HandleFunc("/api/user/2fa/register", ovpnAdmin.UserSetupTFAHandler)
|
http.HandleFunc("/api/user/2fa/register", ovpnAdmin.UserSetupTFAHandler)
|
||||||
http.HandleFunc("/api/user/2fa/reset", ovpnAdmin.UserResetTFAHandler)
|
http.HandleFunc("/api/user/2fa/reset", ovpnAdmin.UserResetTFAHandler)
|
||||||
|
|
|
@ -7,7 +7,7 @@ auth_usr=$(head -1 $1)
|
||||||
auth_secret=$(tail -1 $1)
|
auth_secret=$(tail -1 $1)
|
||||||
|
|
||||||
if [ $common_name = $auth_usr ]; then
|
if [ $common_name = $auth_usr ]; then
|
||||||
curl -s --fail --data-raw 'username='${auth_usr} --data-raw 'secret='${auth_secret} localhost:8080/api/auth/check
|
curl -s --fail --data-raw 'username='${auth_usr} --data-raw 'token='${auth_secret} localhost:8080/api/auth/check
|
||||||
else
|
else
|
||||||
echo "$(date) Authorization for user $common_name failed"
|
echo "$(date) Authorization for user $common_name failed"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
|
@ -41,7 +41,7 @@ fi
|
||||||
|
|
||||||
cp -f /etc/openvpn/setup/openvpn.conf /etc/openvpn/openvpn.conf
|
cp -f /etc/openvpn/setup/openvpn.conf /etc/openvpn/openvpn.conf
|
||||||
|
|
||||||
if [ ${OVPN_PASSWD_AUTH} = "true" ]; then
|
if [ ${OVPN_AUTH} == "TOTP" ] || [ ${OVPN_AUTH} == "PASSWORD" ]; then
|
||||||
mkdir -p /etc/openvpn/scripts/
|
mkdir -p /etc/openvpn/scripts/
|
||||||
cp -f /etc/openvpn/setup/auth.sh /etc/openvpn/scripts/auth.sh
|
cp -f /etc/openvpn/setup/auth.sh /etc/openvpn/scripts/auth.sh
|
||||||
chmod +x /etc/openvpn/scripts/auth.sh
|
chmod +x /etc/openvpn/scripts/auth.sh
|
||||||
|
|
Loading…
Reference in a new issue