Skip to content

Commit

Permalink
Merge pull request wso2#150 from tharindulak/auth
Browse files Browse the repository at this point in the history
Add refactored docker auth plugin implementation
  • Loading branch information
nadundesilva authored Sep 19, 2019
2 parents 9989db0 + 87d1765 commit e2be40c
Show file tree
Hide file tree
Showing 71 changed files with 767 additions and 9,378 deletions.
36 changes: 0 additions & 36 deletions Gopkg.lock

This file was deleted.

34 changes: 0 additions & 34 deletions Gopkg.toml

This file was deleted.

34 changes: 20 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ PROJECT_ROOT := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
PROJECT_PKG := github.com/cellery-io/cellery-hub
DOCKER_REPO ?= wso2cellery
VERSION ?= latest
DOCKER_AUTH_BASE_HASH := 82573a5f102c2d886428415bf6fcb8d94706834a

PROXY := proxy
DOCKER_AUTH := docker-auth
PORTAL := portal
API := api
IDENTITY_SERVER_CUSTOMIZATION := identity-server-customization
AUTH_SERVER := auth-server
DOCKER_AUTH_BASE := docker-auth-base
COMPONENTS := $(PROXY) $(DOCKER_AUTH) $(PORTAL) $(API) $(IDENTITY_SERVER_CUSTOMIZATION)

CLEAN_TARGETS := $(addprefix clean., $(COMPONENTS))
Expand Down Expand Up @@ -161,9 +162,7 @@ build.$(PROXY): clean.$(PROXY) init.$(PROXY)

.PHONY: build.$(DOCKER_AUTH)
build.$(DOCKER_AUTH): clean.$(DOCKER_AUTH) init.$(DOCKER_AUTH)
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./components/$(DOCKER_AUTH)/target/authentication ./components/$(DOCKER_AUTH)/cmd/authn/authentication.go
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./components/$(DOCKER_AUTH)/target/authorization ./components/$(DOCKER_AUTH)/cmd/authz/authorization.go
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./components/$(DOCKER_AUTH)/target/auth_server ./components/$(DOCKER_AUTH)/cmd/authserver/
@:

.PHONY: build.$(PORTAL)
build.$(PORTAL): clean.$(PORTAL) init.$(PORTAL)
Expand Down Expand Up @@ -209,19 +208,23 @@ docker.$(PROXY): build.$(PROXY)
cd ./docker/$(PROXY); \
docker build -t $(DOCKER_REPO)/cellery-hub-proxy:$(VERSION) .

.PHONY: docker.$(DOCKER_AUTH_BASE)
docker.$(DOCKER_AUTH_BASE):
rm -rf ./docker/$(DOCKER_AUTH)/$(DOCKER_AUTH_BASE)/target
mkdir -p ./docker/$(DOCKER_AUTH)/$(DOCKER_AUTH_BASE)/target
cd ./docker/$(DOCKER_AUTH)/$(DOCKER_AUTH_BASE)/target; \
git clone https://github.com/cesanta/docker_auth.git
cd ./docker/$(DOCKER_AUTH)/$(DOCKER_AUTH_BASE)/target/docker_auth; \
git checkout $(DOCKER_AUTH_BASE_HASH)
cd ./docker/$(DOCKER_AUTH)/$(DOCKER_AUTH_BASE); \
docker build -t $(DOCKER_REPO)/$(DOCKER_AUTH_BASE):$(DOCKER_AUTH_BASE_HASH) .

.PHONY: docker.$(DOCKER_AUTH)
docker.$(DOCKER_AUTH): build.$(DOCKER_AUTH)
docker.$(DOCKER_AUTH):
rm -rf ./docker/$(DOCKER_AUTH)/target
rm -rf ./docker/$(DOCKER_AUTH)/$(AUTH_SERVER)/target
mkdir ./docker/$(DOCKER_AUTH)/target/
cp ./components/$(DOCKER_AUTH)/target/authentication ./docker/$(DOCKER_AUTH)/target/
cp ./components/$(DOCKER_AUTH)/target/authorization ./docker/$(DOCKER_AUTH)/target/
mkdir ./docker/$(DOCKER_AUTH)/$(AUTH_SERVER)/target/
cp ./components/$(DOCKER_AUTH)/target/auth_server ./docker/$(DOCKER_AUTH)/$(AUTH_SERVER)/target/
cp -r ./components/docker-auth ./docker/$(DOCKER_AUTH)/target/
cd ./docker/$(DOCKER_AUTH); \
docker build -t $(DOCKER_REPO)/cellery-hub-docker-auth:$(VERSION) .
cd ./docker/$(DOCKER_AUTH)/$(AUTH_SERVER); \
docker build -t $(DOCKER_REPO)/cellery-hub-docker-auth-server:$(VERSION) .

.PHONY: docker.$(PORTAL)
docker.$(PORTAL): build.$(PORTAL)
Expand All @@ -246,10 +249,13 @@ docker.$(IDENTITY_SERVER_CUSTOMIZATION): build.$(IDENTITY_SERVER_CUSTOMIZATION)
docker-push.$(PROXY):
docker push $(DOCKER_REPO)/cellery-hub-proxy:$(VERSION)

.PHONY: docker-push.$(DOCKER_AUTH_BASE)
docker-push.$(DOCKER_AUTH_BASE):
docker push $(DOCKER_REPO)/$(DOCKER_AUTH_BASE):$(DOCKER_AUTH_BASE_HASH)

.PHONY: docker-push.$(DOCKER_AUTH)
docker-push.$(DOCKER_AUTH):
docker push $(DOCKER_REPO)/cellery-hub-docker-auth:$(VERSION)
docker push $(DOCKER_REPO)/cellery-hub-docker-auth-server:$(VERSION)

.PHONY: docker-push.$(PORTAL)
docker-push.$(PORTAL):
Expand Down
135 changes: 44 additions & 91 deletions components/docker-auth/cmd/authn/authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,123 +19,76 @@
package main

import (
"log"
"net/http"
"os"
"fmt"
"strconv"
"strings"

"github.com/cesanta/docker_auth/auth_server/api"
"go.uber.org/zap"

"github.com/cellery-io/cellery-hub/components/docker-auth/pkg/auth"
"github.com/cellery-io/cellery-hub/components/docker-auth/pkg/extension"
)

const (
logFile = "/extension-logs/authn-ext.log"
)
var logger *zap.SugaredLogger

func main() {
err := os.MkdirAll("/extension-logs", os.ModePerm)
file, err := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
defer func() {
err = file.Close()
if err != nil {
log.Printf("Error while closing the file : %s\n", err)
os.Exit(extension.MisuseExitCode)
}
}()
if err != nil {
log.Println("Error creating the file :", err)
os.Exit(extension.ErrorExitCode)
type PluginAuthn struct {
}

func (*PluginAuthn) Authenticate(user string, password api.PasswordString) (bool, api.Labels, error) {
if logger == nil {
logger = extension.NewLogger()
}
log.SetOutput(file)
return doAuthentication(user, string(password), logger)
}

func (*PluginAuthn) Stop() {
}

func (*PluginAuthn) Name() string {
return "plugin auth"
}

var Authn PluginAuthn

execId, err := extension.GetExecID()
func doAuthentication(user, incomingToken string, logger *zap.SugaredLogger) (bool, api.Labels, error) {
execId, err := extension.GetExecID(logger)
if err != nil {
log.Printf("Error in generating the execId : %s\n", err)
os.Exit(extension.ErrorExitCode)
return false, nil, fmt.Errorf("error in generating the execId : %s", err)
}

text := extension.ReadStdIn()
log.Printf("[%s] Payload received from CLI : %s\n", execId, text)
credentials := strings.Split(text, " ")
logger.Debugf("[%s] Username %q and password received from CLI", execId, user)

if len(credentials) != 2 {
log.Printf("[%s] Cannot parse the Input from the Auth service", execId)
os.Exit(extension.ErrorExitCode)
}
uName := credentials[0]
incomingToken := credentials[1]
tokenArray := strings.Split(incomingToken, ":")
token := tokenArray[0]

isPing := len(tokenArray) > 1 && tokenArray[1] == "ping"
if isPing {
log.Printf("[%s] Ping request recieved\n", execId)
logger.Debugf("[%s] Ping request received", execId)
}

url := resolveAuthenticationUrl(execId)
if url == "" {
log.Printf("[%s] Authentication end point not found. Exiting with error exit code", execId)
os.Exit(extension.ErrorExitCode)
isAuthenticated, err := auth.Authenticate(user, token, logger, execId)
if err != nil {
return false, nil, fmt.Errorf("error while authenticating %v", err)
}
payload := strings.NewReader("{\"uName\":\"" + uName + "\",\"token\":\"" + token + "\"}")

log.Printf("[%s] Calling %s", execId, url)
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add(extension.ExecIdHeaderName, execId)
res, _ := http.DefaultClient.Do(req)

defer func() {
err := res.Body.Close()
if err != nil {
log.Printf("[%s] Error occured while closing the response received from auth server "+
" : %v\n", execId, err)
}
}()

log.Printf("[%s] Response received from the auth server with the status code %d", execId, res.StatusCode)

if res.StatusCode == http.StatusUnauthorized {
log.Printf("[%s] User access token failed to authenticate. Evaluating ping", execId)
if !isAuthenticated {
logger.Debugf("[%s] User access token failed to authenticate. Evaluating ping", execId)
if isPing {
log.Printf("[%s] Since this is a ping request, exiting with auth fail status without passing to "+
" authorization filter\n", execId)
os.Exit(extension.ErrorExitCode)
return false, nil, fmt.Errorf("since this is a ping request, exiting with auth fail status " +
"without passing to authorization filter")
} else {
log.Printf("[%s] Failed authentication. But passing to authorization filter", execId)
addAuthenticationLabel(false, execId)
os.Exit(extension.SuccessExitCode)
logger.Debugf("[%s] Failed authentication. But passing to authorization filter", execId)
return true, makeAuthenticationLabel(false), nil
}
}
if res.StatusCode == http.StatusOK {
log.Printf("[%s] User successfully authenticated by validating token. Exiting with success exit code",
execId)
addAuthenticationLabel(true, execId)
os.Exit(extension.SuccessExitCode)
} else {
logger.Debugf("[%s] User successfully authenticated by validating token", execId)
return true, makeAuthenticationLabel(true), nil
}
}

// resolves the authentication end point from the environment variables.
func resolveAuthenticationUrl(execId string) string {
authServer := os.Getenv("AUTH_SERVER_URL")
authenticationEP := os.Getenv("AUTHENTICATION_END_POINT")
if len(authServer) == 0 {
log.Printf("[%s] Error: AUTH_SERVER environment variable is empty\n", execId)
return ""
}
if len(authenticationEP) == 0 {
log.Printf("[%s] Error: AUTHENTICATION_END_POINT environment variable is empty\n", execId)
return ""
}
return authServer + authenticationEP
}

func addAuthenticationLabel(isAuthenticated bool, execId string) {
func makeAuthenticationLabel(isAuthenticated bool) api.Labels {
authResultString := strconv.FormatBool(isAuthenticated)
label := "{\"labels\": {\"isAuthSuccess\": [\"" + authResultString + "\"]}}"
log.Printf("[%s] Adding labels to authorization ext from authn ext: %s\n", execId, label)
_, err := os.Stdout.WriteString(label)
if err != nil {
log.Printf("[%s] Error in writing to standard output. Hence failing authentication. No authorizatino done", err)
os.Exit(extension.ErrorExitCode)
}
authLabels := api.Labels{}
authLabels["isAuthSuccess"] = []string{authResultString}
return authLabels
}
Loading

0 comments on commit e2be40c

Please sign in to comment.