Skip to content
Snippets Groups Projects
Unverified Commit c56df012 authored by meskio's avatar meskio :tent: Committed by Kali Kaneko
Browse files

[feat] expose auth API in pkg/vpn

Be able to check if it needs auth and then be able to login. Use the
logged in token for fetching the cert.
parent 8bb41cff
No related branches found
No related tags found
No related merge requests found
......@@ -28,4 +28,6 @@ type Bitmask interface {
ListGateways(provider string) ([]string, error)
UseGateway(name string) error
UseTransport(transport string) error
NeedsCredentials() bool
DoLogin(username, password string) (bool, error)
}
......@@ -25,6 +25,5 @@ type credentials struct {
type authentication interface {
needsCredentials() bool
getToken(cred *credentials) ([]byte, error)
getPemCertificate(cred *credentials) ([]byte, error)
getToken(user, password string) ([]byte, error)
}
......@@ -17,40 +17,16 @@ package bonafide
import (
"errors"
"fmt"
"io/ioutil"
)
type anonymousAuthentication struct {
client httpClient
authURI string
certURI string
client httpClient
}
func (a *anonymousAuthentication) needsCredentials() bool {
return true
}
func (a *anonymousAuthentication) getPemCertificate(cred *credentials) ([]byte, error) {
resp, err := a.client.Post(certAPI, "", nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 404 {
resp, err = a.client.Post(certAPI3, "", nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("Get vpn cert has failed with status: %s", resp.Status)
}
return ioutil.ReadAll(resp.Body)
}
func (a *anonymousAuthentication) getToken(cred *credentials) ([]byte, error) {
func (a *anonymousAuthentication) getToken(user, password string) ([]byte, error) {
return []byte(""), errors.New("anon authentication should not call getToken")
}
......@@ -26,34 +26,18 @@ import (
type sipAuthentication struct {
client httpClient
authURI string
certURI string
}
func (a *sipAuthentication) needsCredentials() bool {
return true
}
func (a *sipAuthentication) getPemCertificate(cred *credentials) ([]byte, error) {
if cred == nil {
return nil, fmt.Errorf("Need bonafide credentials for sip auth")
}
token, err := a.getToken(cred)
if err != nil {
return nil, fmt.Errorf("Error while getting token: %s", err)
}
cert, err := a.getProtectedCert(a.certURI, string(token))
if err != nil {
return nil, fmt.Errorf("Error while getting cert: %s", err)
}
return cert, nil
}
func (a *sipAuthentication) getToken(cred *credentials) ([]byte, error) {
func (a *sipAuthentication) getToken(user, password string) ([]byte, error) {
/* TODO
[ ] get token from disk?
[ ] check if expired? set a goroutine to refresh it periodically?
*/
credJSON, err := formatCredentials(cred.User, cred.Password)
credJSON, err := formatCredentials(user, password)
if err != nil {
return nil, fmt.Errorf("Cannot encode credentials: %s", err)
}
......@@ -68,20 +52,6 @@ func (a *sipAuthentication) getToken(cred *credentials) ([]byte, error) {
return ioutil.ReadAll(resp.Body)
}
func (a *sipAuthentication) getProtectedCert(uri, token string) ([]byte, error) {
req, err := http.NewRequest("POST", uri, strings.NewReader(""))
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
resp, err := a.client.Do(req)
if err != nil {
return nil, fmt.Errorf("Error while getting token: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("Error %d", resp.StatusCode)
}
return ioutil.ReadAll(resp.Body)
}
func formatCredentials(user, pass string) (string, error) {
c := credentials{User: user, Password: pass}
credJSON, err := json.Marshal(c)
......
......@@ -25,6 +25,7 @@ import (
"io/ioutil"
"log"
"net/http"
"strings"
"time"
"0xacab.org/leap/bitmask-vpn/pkg/config"
......@@ -50,7 +51,7 @@ type Bonafide struct {
eip *eipService
tzOffsetHours int
auth authentication
credentials credentials
token []byte
apiURL string
}
......@@ -101,28 +102,29 @@ func New() *Bonafide {
switch auth := config.Auth; auth {
case "sip":
log.Println("Client expects sip auth")
b.auth = &sipAuthentication{client, b.getURL("auth"), b.getURL("certv3")}
b.auth = &sipAuthentication{client, b.getURL("auth")}
case "anon":
log.Println("Client expects anon auth")
b.auth = &anonymousAuthentication{client, "", b.getURL("certv3")}
b.auth = &anonymousAuthentication{client}
default:
log.Println("Client expects invalid auth", auth)
b.auth = &anonymousAuthentication{client, "", b.getURL("certv3")}
b.auth = &anonymousAuthentication{client}
}
return b
}
func (b *Bonafide) NeedsCredentials() bool {
return b.auth.needsCredentials()
}
func (b *Bonafide) DoLogin(username, password string) (bool, error) {
if !b.auth.needsCredentials() {
return false, errors.New("Auth method does not need login")
}
cred := credentials{username, password}
b.credentials = cred
/* TODO keep this in memory */
_, err := b.auth.getToken(&cred)
var err error
b.token, err = b.auth.getToken(username, password)
if err != nil {
return false, err
}
......@@ -130,24 +132,39 @@ func (b *Bonafide) DoLogin(username, password string) (bool, error) {
return true, nil
}
func (b *Bonafide) checkCredentialsAreSet() bool {
if b.credentials.User == "" || b.credentials.Password == "" {
log.Println("BUG: expected credentials to be set")
return false
}
return true
}
func (b *Bonafide) GetPemCertificate() ([]byte, error) {
if b.auth == nil {
log.Fatal("ERROR: bonafide did not initialize auth")
}
if b.auth.needsCredentials() {
b.checkCredentialsAreSet()
if b.auth.needsCredentials() && b.token == nil {
log.Println("BUG: expected token to be set, but is not there")
return nil, errors.New("Needs to login, but it was not logged in. Please, restart the application and report it if it continues happening")
}
req, err := http.NewRequest("POST", b.getURL("certv3"), strings.NewReader(""))
if err != nil {
return nil, err
}
if b.token != nil {
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", b.token))
}
resp, err := b.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 404 {
resp, err = b.client.Post(b.getURL("cert"), "", nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("Get vpn cert has failed with status: %s", resp.Status)
}
cert, err := b.auth.getPemCertificate(&b.credentials)
return cert, err
return ioutil.ReadAll(resp.Body)
}
func (b *Bonafide) getURL(object string) string {
......
......@@ -73,7 +73,7 @@ func (b *Bonafide) setupAuthentication(i interface{}) {
case "anon":
// Do nothing, we're set on initialization.
case "sip":
b.auth = &sipAuthentication{b.client, b.getURL("auth"), b.getURL("certv3")}
b.auth = &sipAuthentication{b.client, b.getURL("auth")}
default:
log.Printf("BUG: unknown authentication method %s", auth)
}
......
......@@ -92,3 +92,11 @@ func (b *Bitmask) Close() {
func (b *Bitmask) Version() (string, error) {
return "", nil
}
func (b *Bitmask) NeedsCredentials() bool {
return b.bonafide.NeedsCredentials()
}
func (b *Bitmask) DoLogin(username, password string) (bool, error) {
return b.bonafide.DoLogin(username, password)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment