Commit 9a275a4e authored by Caro Axel's avatar Caro Axel Committed by Loïck Bonniot

[c] Add auth command

parent d6abf53a
Pipeline #273 passed with stage
......@@ -38,6 +38,7 @@ func init() {
fmt.Println(" help print this help")
fmt.Println(" version print dfss client version")
fmt.Println(" register register a new client")
fmt.Println(" auth authenticate a new client")
fmt.Println(" show <c> print contract information from file c")
fmt.Println("\nFlags:")
......@@ -86,6 +87,18 @@ func main() {
fmt.Println("An error occurred : ", err.Error())
}
case "authenticate":
fmt.Println("Authenticating user")
var mail, token string
readStringParam("Mail", "", &mail)
readStringParam("Token", "", &token)
err := user.Authenticate(fca, fcert, addrPort, mail, token)
if err != nil {
fmt.Println("An error occurred : ", err.Error())
}
case "show":
showContract(flag.Arg(1))
default:
......
package user
import (
"dfss/dfssc/common"
"dfss/dfssc/security"
pb "dfss/dfssp/api"
"errors"
"io/ioutil"
"regexp"
"time"
"golang.org/x/net/context"
)
// AuthManager handles the authentication of a user
type AuthManager struct {
fileCA string
fileCert string
addrPort string
mail string
token string
}
// NewAuthManager creates a new authentication manager with the given parameters
func NewAuthManager(fileCA, fileCert, addrPort, mail, token string) (*AuthManager, error) {
m := &AuthManager{
fileCA: fileCA,
fileCert: fileCert,
addrPort: addrPort,
mail: mail,
token: token,
}
if err := m.checkValidParams(); err != nil {
return nil, err
}
if err := m.checkFilePresence(); err != nil {
return nil, err
}
return m, nil
}
func (m *AuthManager) checkValidParams() error {
re, _ := regexp.Compile(`.+@.+\..+`)
if b := re.MatchString(m.mail); !b {
return errors.New("Provided mail is not valid")
}
return nil
}
func (m *AuthManager) checkFilePresence() error {
if b := common.FileExists(m.fileCert); b {
return errors.New("A certificate is already present at path " + m.fileCert)
}
if b := common.FileExists(m.fileCA); !b {
return errors.New("You need the certificate of the platform at path " + m.fileCA)
}
data, err := security.GetCertificate(m.fileCA)
if err != nil {
return err
}
if time.Now().After(data.NotAfter) {
return errors.New("Root certificate has expired")
}
return nil
}
// Authenticate performs the authentication request
// (ie connection to the platform grpc server, sending of the request, handling the response)
func (m *AuthManager) Authenticate() error {
response, err := m.sendRequest()
if err != nil {
return err
}
err = m.evaluateResponse(response)
if err != nil {
return err
}
return nil
}
// Creates the associated authentication request and sends it to the platform grpc server
func (m *AuthManager) sendRequest() (*pb.RegisteredUser, error) {
client, err := connect(m.fileCA, m.addrPort)
if err != nil {
return nil, err
}
// gRPC request
request := &pb.AuthRequest{
Email: m.mail,
Token: m.token,
}
// Stop the context if it takes too long for the platform to answer
ctx, cancel := context.WithTimeout(context.TODO(), 10*time.Second)
defer cancel()
response, err := client.Auth(ctx, request)
if err != nil {
return nil, err
}
return response, nil
}
// Handle the platform grpc server's reponse to the authentication request
func (m *AuthManager) evaluateResponse(response *pb.RegisteredUser) error {
cert := []byte(response.ClientCert)
err := ioutil.WriteFile(m.fileCert, cert, 0600)
if err != nil {
return err
}
return nil
}
package user
import (
"dfss/dfssc/common"
"fmt"
"github.com/bmizerany/assert"
"os"
"testing"
)
func TestAuthenticationValidation(t *testing.T) {
_, err := NewAuthManager("fca", fcert, addrPort, "dummy", "token")
assert.T(t, err != nil, "Email is invalid")
f, _ := os.Create(fcert)
_ = f.Close()
_, err = NewAuthManager("fca", fcert, addrPort, "mail@mail.mail", "token")
assert.T(t, err != nil, "Cert file already there")
_ = os.Remove(fcert)
_, err = NewAuthManager("fca", fcert, addrPort, "mail@mail.mail", "token")
assert.T(t, err != nil, "CA file not there")
_, err = NewAuthManager(fca, fcert, addrPort, "mail@mail.mail", "token")
assert.Equal(t, err, nil)
}
func ExampleAuthenticate() {
manager, err := NewAuthManager(fca, fcert, addrPort, "mail@mail.mail", "token")
if err != nil {
fmt.Println(err.Error())
}
fmt.Println("Manager successfully created")
err = manager.Authenticate()
if err != nil {
fmt.Println(err.Error())
}
fmt.Println("Manager said authentication went fine")
if b := common.FileExists(fcert); !b {
fmt.Println("The cert file was not saved to disk")
} else {
fmt.Println("The cert file was saved to disk")
_ = os.Remove(fcert)
}
// Output:
// Manager successfully created
// Manager said authentication went fine
// The cert file was saved to disk
}
// Package user handles all the user-related logic
package user
import (
"dfss/dfssc/security"
pb "dfss/dfssp/api"
"dfss/net"
)
// Register a user using the provided parameters
func Register(fileCA, fileCert, fileKey, addrPort, passphrase, country, organization, unit, mail string, bits int) error {
manager, err := NewRegisterManager(fileCA, fileCert, fileKey, addrPort, passphrase, country, organization, unit, mail, bits)
......@@ -15,3 +21,32 @@ func Register(fileCA, fileCert, fileKey, addrPort, passphrase, country, organiza
return nil
}
// Authenticate a user using the provided parameters
func Authenticate(fileCA, fileCert, addrPort, mail, token string) error {
manager, err := NewAuthManager(fileCA, fileCert, addrPort, mail, token)
if err != nil {
return err
}
err = manager.Authenticate()
if err != nil {
return err
}
return nil
}
func connect(fileCA, addrPort string) (pb.PlatformClient, error) {
ca, err := security.GetCertificate(fileCA)
if err != nil {
return nil, err
}
conn, err := net.Connect(addrPort, nil, nil, ca)
if err != nil {
return nil, err
}
return pb.NewPlatformClient(conn), nil
}
......@@ -4,7 +4,6 @@ import (
"dfss/dfssc/common"
"dfss/dfssc/security"
pb "dfss/dfssp/api"
"dfss/net"
"errors"
"regexp"
"time"
......@@ -138,12 +137,7 @@ func (m *RegisterManager) buildCertificateRequest() (string, error) {
// Send the request and returns the response
func (m *RegisterManager) sendRequest(certRequest string) (*pb.ErrorCode, error) {
ca, err := security.GetCertificate(m.fileCA)
if err != nil {
return nil, err
}
conn, err := net.Connect(m.addrPort, nil, nil, ca)
client, err := connect(m.fileCA, m.addrPort)
if err != nil {
return nil, err
}
......@@ -154,7 +148,6 @@ func (m *RegisterManager) sendRequest(certRequest string) (*pb.ErrorCode, error)
Request: certRequest,
}
client := pb.NewPlatformClient(conn)
// Stop the context if it takes too long for the platform to answer
ctx, cancel := context.WithTimeout(context.TODO(), 10*time.Second)
defer cancel()
......
......@@ -65,7 +65,7 @@ func TestMain(m *testing.M) {
}
// Test the validation of the fields
func TestValidation(t *testing.T) {
func TestRegisterValidation(t *testing.T) {
_, err := NewRegisterManager(fca, fcert, fkey, addrPort, "password", "FR", "organization", "unit", "dummy", 2048)
assert.T(t, err != nil, "Email is invalid")
......@@ -97,15 +97,15 @@ func TestGetCertificate(t *testing.T) {
err = manager.GetCertificate()
assert.T(t, err == nil, "An error occurred while getting the certificate")
go testInvalidResponse(t, "dfss@invarg.io")
go testInvalidResponse(t, "dfss@badauth.io")
go testInvalidResponse(t, "dfss@warning.io")
go testInvalidResponse(t, "dfss@interr.io")
go testInvalidResponse(t, "dfss@inexistant.io")
go testRegisterInvalidResponse(t, "dfss@invarg.io")
go testRegisterInvalidResponse(t, "dfss@badauth.io")
go testRegisterInvalidResponse(t, "dfss@warning.io")
go testRegisterInvalidResponse(t, "dfss@interr.io")
go testRegisterInvalidResponse(t, "dfss@inexistant.io")
}
// Test an invalid error code and check we get an error
func testInvalidResponse(t *testing.T, mail string) {
func testRegisterInvalidResponse(t *testing.T, mail string) {
manager, err := NewRegisterManager(fca, fcert+mail, fkey+mail, addrPort, "password", "FR", "organization", "unit", mail, 2048)
assert.T(t, err == nil, "An error occurred while processing")
......
package fixtures
import (
pb "dfss/dfssp/api"
)
// AuthFixture holds the fixture for the Auth route
var AuthFixture = map[string]*pb.RegisteredUser{
"default": &pb.RegisteredUser{ClientCert: "default"},
}
......@@ -6,7 +6,7 @@ import (
)
// RegisterFixture holds the fixture for the Register route
var RegisterFixture map[string]*pb.ErrorCode = map[string]*pb.ErrorCode{
var RegisterFixture = map[string]*pb.ErrorCode{
"dfss@success.io": &pb.ErrorCode{
Code: pb.ErrorCode_SUCCESS,
Message: "SUCCESS",
......
......@@ -32,8 +32,7 @@ func (s *mockServer) Register(ctx context.Context, in *api.RegisterRequest) (*ap
//
// Handle incoming AuthRequest messages
func (s *mockServer) Auth(ctx context.Context, in *api.AuthRequest) (*api.RegisteredUser, error) {
// TODO
return nil, nil
return fixtures.AuthFixture["default"], nil
}
// Unregister handler
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment