/mobile-security-service

Primary LanguageGoApache License 2.0Apache-2.0

Mobile Security Service

Overview

This is the server component of the AeroGear Mobile Security Service. It is a RESTful API that allows developers to view, enable and disable specific versions of applications on demand, with the information stored in a PostgreSQL database.

Prerequisites

Install Golang

Ensure the $GOPATH environment variable is set

Install the dep package manager

Install Docker and Docker Compose

Getting Started

If you’d like to simply run the entire application in docker-compose, follow these instructions.

Golang projects are kept in a workspace that follows a very specific architecture. Before cloning this repo, be sure you have a $GOPATH environment variable set up.

.1. Cloning the Repository

git clone git@github.com:aerogear/mobile-security-service.git $GOPATH/src/github.com/aerogear/mobile-security-service

.2. Change to correct working directory

cd $GOPATH/src/github.com/aerogear/mobile-security-service

.3. Installing Dependencies

make setup
ℹ️
This is using the dep package manager under the hood. You will see the dependencies installed in the vendor folder.

.4. Configuring the Database

This REST Service is using a PostgreSQL database. The server will not start without a PostgreSQL available. There are two ways to install the database:

.4.1. By using the docker image of this project

  • Removing any existing docker Postgres containers

$ docker rm <container_id>
  • Starting the database container

$ docker-compose up -d db
ℹ️
When the database is started the db.go routine will be executed and the database model will be created.
💡
You can use pgadmin to work with the database. See Installing and configuring client tool for the database
  • Checking the database

    1. Run $ docker ps to get the container id

    2. Run $ docker exec -it <postgres-container-id> bash to access the container via shell

    3. Run psql -U postgres to login with the user postgres in the database

    4. Run \c mobile_security_service to connect to the database created for this project

    5. Run \dt to lists all tables in the current database

.4.2. By using a local Postgres DB

In the Database section you can see the default values which will be used by the config.go routine.

  1. Set up your local database and/or change the configuration defined.

  2. Create the database and tables in your local PostgreSQL installation. See the file db.go to get the scripts to create the tables.

ℹ️
The file config.go will use the default values, however, if would like to change them it should be made by Environment Variables, see the topic Adding your own .env file

.5. Starting the Server

go run cmd/mobile-security-service/main.go

Starting the Server and the web UI

make serve

.6. Checking REST Service

Run the following curl command and check the output is as shown.

$ curl localhost:3000/api/apps
[{"id":"0890506c-3dd1-43ad-8a09-21a4111a65a6","appId":"com.aerogear.testapp","appName":"Test App","numOfDeployedVersions":2,"numOfCurrentInstalls":3,"numOfAppLaunches":6000},{"id":"1b9e7a5f-af7c-4055-b488-72f2b5f72266","appId":"com.aerogear.foobar","appName":"Foobar","numOfDeployedVersions":0,"numOfCurrentInstalls":0,"numOfAppLaunches":0}]
ℹ️
This endpoint will return all apps saved in the database. If you do not have data saved locally it will return no data with a 204 No Content response code.
💡
You can install the Postman tool which will be useful to call and test the REST API endpoints of this server. Following an image to show how it works.

.7. Running Entire Application with Docker Compose

This section shows how to start the entire application with docker-compose. This is useful for doing some quick tests (using the SDKs) for example.

First, compile a Linux compatible binary:

go build -o mobile-security-service cmd/mobile-security-service/main.go

This binary will be used to build the Docker image. Now start the entire application.

docker-compose up

Setup and configurations

Environment Variables

The mobile-security-service is configured using environment variables.

  • By default, the application will look for system environment variables to use.

  • If a system environment variable cannot be found, the application will then check the .env file in the application root.

  • If the .env file does not exist, or if the variable is not defined in the file, the application will use the default value defined in config.go.

Adding your own .env file

Make a copy of the example file .env.example.

cp .env.example .env

Now the application will use the values defined in .env.

Server Configuration

Variable

Default

Description

PORT

3000

The port the server will listen on

LOG_LEVEL

info

Can be one of [debug, info, warning, error, fatal, panic]

LOG_FORMAT

text

Can be one of [text, json]

ACCESS_CONTROL_ALLOW_ORIGIN

*

Can be multiple URL values separated with commas. Example: ACCESS_CONTROL_ALLOW_ORIGIN=http://www.example.com,http://example.com

ACCESS_CONTROL_ALLOW_CREDENTIALS

false

Can be one of [true, false]

DBMAX_CONNECTIONS

100

The maximum number of concurrent database connections the server will open

Database

The database connection is configured using the table of environment variables below. These environment variables correspond to the PostgreSQL libpq environment variables. The table below shows all of the environment variables supported by the pq driver used in this server.

Variable

Default

Description

PGDATABASE

mobile_security_service

The database to connect to

PGUSER

postgresql

The database user

PGPASSWORD

postgres

The database password

PGHOST

localhost

The database hostname to connect to

PGPORT

5432

The database port to connect to

PGSSLMODE

disable

The SSL mode

PGCONNECT_TIMEOUT

5

The default connection timeout (seconds)

PGAPPNAME

The application_name connection parameter

PGSSLCERT

The sslcert connection parameter.

PGSSLKEY

The sslkey connection parameter.

PGSSLROOTCERT

The sslrootcert connection parameter

Database Entity Relationship Diagram

Diagram

Development information for contributors

Using Swagger UI

By browser

The swagger api doc is generated in /api/swagger.yaml and you can check the REST API definition with this file by using the Demo tool online for swaggerUI or Chrome extension. Paste https://raw.githubusercontent.com/aerogear/mobile-security-service/master/api/swagger.yaml and press Explore.

By docker

A Swagger UI can be used for testing the mobile-security-service service.

docker run -p 8080:8080 -e API_URL=https://raw.githubusercontent.com/aerogear/mobile-security-service/master/api/swagger.yaml swaggerapi/swagger-ui

Or you can run the container with docker-compose up -d swagger.

The Swagger UI is available at localhost:8080.

Building & Testing

The Makefile provides commands for building and testing the code. Some dependencies are required to run these commands.

Installing the required dependencies

Dependencies may be required to run some of the Make commands. Below are instructions on how to install them.

Run the following command.

$ go get -u github.com/matryer/moq

NOTE : See all commands available in Using make commands

Installing and configuring client tool for the database

You can use pgadmin which is the client tool for PostgreSQL to work with the database.

  • Download and install the client tool

ℹ️
The link to download for MacOS is : https://www.pgadmin.org/download/pgadmin-4-macos/
  • Configure the client tool

Following the steps to do this setup.

  1. Access the tool via the browser. The default link will be http://127.0.0.1:52263/browser/#

  2. Create a new server connection with the database. Following the image to show how to do it.

Create Server
  1. Add the data required to connect to the database. See the values defined in config.go. Following an image with this setup.

Configuration

Adding data to test the Service

Use the scripts from the file db_seed.go. It will allow you have data to check this service.

Creating mock files for the interfaces

This project is using the dependency moq. Follow the steps below to use it.

  • Creating the mock file

Execute the following command to generate the mock file.

$ moq -out <name_of_mock_file> . <name of interface>

Example:

moq -out apps_service_mock.go . Service
This command need to be executed from the same directory where the interface is or it need to be called as, for example, $ moq -out ./pkg/web/apps/apps_service_mock.go ./pkg/web/apps Service
ℹ️
See more over it in the Readme of moq
  • Using the mock

In the created file you will see an implementation commented as in the following example. This implementation will be used in the test file to mock the methods/func of this interface.

// AppServiceMock is a mock implementation of Service.
//
//     func TestSomethingThatUsesAppService(t *testing.T) {
//
//         // make and configure a mocked Service
//         mockedAppService := &AppServiceMock{
//             GetAppsFunc: func() (*[]models.App, error) {
// 	               panic("mock out the GetApps method")
//             },
//         }
//
//         // use mockedAppService in code that requires Service
//         // and then make assertions.
//
//     }
  • Mocking interfaces

The panic statement needs to be replaced for the mock data. Following an example.

numOfDeployedVersions := 5
numOfAppLaunches := 1000
numOfCurrentInstalls := 9000

// mock data
app := models.App{
    ID:                    "a0874c82-2b7f-11e9-b210-d663bd873d93",
    AppID:                 "com.aerogear.app1",
    AppName:               "app1",
    NumOfDeployedVersions: &numOfDeployedVersions,
    NumOfAppLaunches:      &numOfAppLaunches,
    NumOfCurrentInstalls:  &numOfCurrentInstalls,
}

// make and configure a mocked Service
mockedAppService := &AppServiceMock{
    GetAppsFunc: func() (*[]models.App, error) {
        return &[]models.App{
            app,
        }, nil
    },
}
  • Calling the mock

You will call the mock instead of use the interface. It will return the data mocked as defined above. Following an practical example.

func Test_HttpHandler_GetApps(t *testing.T) {
	// make and configure a mocked Service
	mockedAppService := &AppServiceMock{
		GetAppsFunc: func() (*[]models.App, error) {
			return &[]models.App{
				*helpers.GetMockApp(),
			}, nil
		},
	}

	// Setup
	e := echo.New()
	req := httptest.NewRequest(http.MethodGet, "/", nil)
	rec := httptest.NewRecorder()
	c := e.NewContext(req, rec)
	c.SetPath("/api/apps")
	h := &httpHandler{mockedAppService}
}
ℹ️
The mock file generated by the dep contains comments which will help you to understand how to use it.

Using make commands

Command

Description

make setup

Downloads dependencies into vendor

make setup-githooks

Symlink all Git hooks from .githooks into .git/hooks

make build

Compile a binary compatible with your current system into ./mobile-security-service

make build-linux

Compile a Linux binary into ./dist/linux_amd64/mobile-security-service

make build-swagger-api

Generate swagger API documentation from the source code

make build-image

Compile a binary and create an image from it.

make build-release-image

Compile a binary and create an image with a release tag

make build-master-image

Compile a binary and create an image tagged master

make serve

Runs the server and the UI together

make test

Runs unit tests

make test-all

Runs all tests

make test-integration

Runs integration tests

make test-integration-cover

Runs integration tests and outputs results to a log file

make errcheck

Checks for unchecked errors using errcheck

make vet

Examines source code and reports suspicious constructs using vet

make fmt

Formats code using gofmt

make clean

Removes binary compiled using make build

make push-release-image

Pushes release image to image hosting repository

make push-master-image

Pushes master image to image hosting repository

make cleanup-coverage-file

Removes lines from the coverage report that do not need to be included

ℹ️
The Makefile is implemented with tasks which you should use to work with.

Built With

  • Golang - Programming language used

  • Echo - Web framework used

Release

Following the steps

  • Create a new tag following the semver, for example:

$ git tag -a 0.1.0 -m "version 0.1.0"
  • Push the new tag to the upstream repository, for example:

$ git push upstream 0.1.0
ℹ️
The image with the tag will be created and pushed to the mobile-security-service image repository by the CI.
⚠️
Do not use letters in the tag such as v. It will not work.

Contributing

All contributions are hugely appreciated. Please see our Contributing Guide for guidelines on how to open issues and pull requests. Please check out our Code of Conduct too.

Questions

There are a number of ways you can get in in touch with us, please see the AeroGear community.