Skip to content

Commit

Permalink
Open VAULT 11 - Proxy Ollama requests for authentication (#13)
Browse files Browse the repository at this point in the history
* feat(proxy): Add microservice to proxy ollama requests

Signed-off-by: Rodney Osodo <[email protected]>

* refactor(proxy): forward auth request rather than proxy

Signed-off-by: Rodney Osodo <[email protected]>

* fix(docker): pass version and commit to docker build

Also update docker base image

---------

Signed-off-by: Rodney Osodo <[email protected]>
  • Loading branch information
rodneyosodo authored Sep 13, 2024
1 parent 4e39dbe commit b4a4fcb
Show file tree
Hide file tree
Showing 22 changed files with 1,202 additions and 2 deletions.
48 changes: 48 additions & 0 deletions .github/workflows/cd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Create and publish Vault Proxy Docker image

on:
push:
branches:
- main
tags:
- "v*"
paths:
- ".github/workflows/cd.yaml"
- "proxy/**"

workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-and-push-image:
runs-on: ubuntu-latest

permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Fetch tags for the build
run: |
git fetch --prune --unshallow --tags
- name: Set up Docker Build
uses: docker/setup-buildx-action@v3

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push Docker image
run: |
cd proxy
make latest
43 changes: 43 additions & 0 deletions .github/workflows/proxy-ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Continuous Integration

on:
pull_request:
branches:
- main
paths:
- ".github/workflows/cd.yaml"
- "proxy/**"

push:
branches:
- main
paths:
- ".github/workflows/cd.yaml"
- "proxy/**"

workflow_dispatch:

jobs:
lint-and-build: # Linting and building are combined to save time for setting up Go
name: Lint and Build
runs-on: ubuntu-latest

steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.23.x
cache-dependency-path: "go.sum"

- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
working-directory: proxy
version: v1.60.1

- name: Build proxy
run: |
cd proxy && make all
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ cloud-init/meta-data

# Traefik files
acme.json

# Proxy Build
proxy/build
11 changes: 10 additions & 1 deletion docker-compose/.env
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ MG_SPICEDB_DB_PORT=5432
### SpiceDB config
MG_SPICEDB_PRE_SHARED_KEY="yejaTYpqgwqn8ACsnt4qzUso9z5auY"
MG_SPICEDB_SCHEMA_FILE="/schema.zed"
MG_SPICEDB_HOST=magistrala-spicedb
MG_SPICEDB_HOST=spicedb
MG_SPICEDB_PORT=50051
MG_SPICEDB_DATASTORE_ENGINE=postgres

Expand Down Expand Up @@ -142,3 +142,12 @@ MG_GOOGLE_STATE=

# Docker image tag
MG_RELEASE_TAG=latest

# Proxy
UV_VAULT_PROXY_LOG_LEVEL=info
UV_VAULT_PROXY_HOST=0.0.0.0
UV_VAULT_PROXY_PORT=8900
UV_VAULT_PROXY_SERVER_CERT=
UV_VAULT_PROXY_SERVER_KEY=
UV_VAULT_PROXY_TARGET_URL=http://ollama:11434
UV_VAULT_PROXY_INSTANCE_ID=
2 changes: 2 additions & 0 deletions docker-compose/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ include:
env_file: .env
- path: ./magistrala-compose.yaml
env_file: .env
- path: ./proxy-compose.yaml
env_file: .env

services:
traefik:
Expand Down
42 changes: 42 additions & 0 deletions docker-compose/proxy-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
services:
vault-proxy:
container_name: vault-proxy
image: ghcr.io/ultravioletrs/vault/proxy:latest
restart: on-failure
networks:
- vault-network
depends_on:
- auth
environment:
UV_VAULT_PROXY_LOG_LEVEL: ${UV_VAULT_PROXY_LOG_LEVEL}
UV_VAULT_PROXY_TARGET_URL: ${UV_VAULT_PROXY_TARGET_URL}
UV_VAULT_PROXY_HOST: ${UV_VAULT_PROXY_HOST}
UV_VAULT_PROXY_PORT: ${UV_VAULT_PROXY_PORT}
UV_VAULT_PROXY_SERVER_CERT: ${UV_VAULT_PROXY_SERVER_CERT}
UV_VAULT_PROXY_SERVER_KEY: ${UV_VAULT_PROXY_SERVER_KEY}
MG_AUTH_GRPC_URL: ${MG_AUTH_GRPC_URL}
MG_AUTH_GRPC_TIMEOUT: ${MG_AUTH_GRPC_TIMEOUT}
MG_AUTH_GRPC_CLIENT_CERT: ${MG_AUTH_GRPC_CLIENT_CERT:+/auth-grpc-client.crt}
MG_AUTH_GRPC_CLIENT_KEY: ${MG_AUTH_GRPC_CLIENT_KEY:+/auth-grpc-client.key}
MG_AUTH_GRPC_SERVER_CA_CERTS: ${MG_AUTH_GRPC_SERVER_CA_CERTS:+/auth-grpc-server-ca.crt}
MG_SEND_TELEMETRY: ${MG_SEND_TELEMETRY}
UV_VAULT_PROXY_INSTANCE_ID: ${UV_VAULT_PROXY_INSTANCE_ID}
MG_JAEGER_URL: ${MG_JAEGER_URL}
MG_JAEGER_TRACE_RATIO: ${MG_JAEGER_TRACE_RATIO}
volumes:
# Auth gRPC client certificates
- type: bind
source: ${MG_AUTH_GRPC_CLIENT_CERT:-ssl/certs/dummy/client_cert}
target: /auth-grpc-client${MG_AUTH_GRPC_CLIENT_CERT:+.crt}
bind:
create_host_path: true
- type: bind
source: ${MG_AUTH_GRPC_CLIENT_KEY:-ssl/certs/dummy/client_key}
target: /auth-grpc-client${MG_AUTH_GRPC_CLIENT_KEY:+.key}
bind:
create_host_path: true
- type: bind
source: ${MG_AUTH_GRPC_SERVER_CA_CERTS:-ssl/certs/dummy/server_ca}
target: /auth-grpc-server-ca${MG_AUTH_GRPC_SERVER_CA_CERTS:+.crt}
bind:
create_host_path: true
4 changes: 4 additions & 0 deletions docker-compose/traefik/dynamic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ http:
stripPrefix:
prefixes:
- "/ollama"
forward-auth-middleware:
forwardAuth:
address: http://vault-proxy:8900

services:
users:
Expand Down Expand Up @@ -107,6 +110,7 @@ http:
service: ollama
middlewares:
- strip-ollama-prefix-middleware
- forward-auth-middleware
- retry-middleware
- headers-middleware
priority: 10
Expand Down
7 changes: 6 additions & 1 deletion docker-compose/traefik/traefik.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ global:
sendAnonymousUsage: false

log:
compress:
compress: true
format: json
level: ERROR

accessLog:
format: json

tracing:
otlp:
http:
endpoint: http://jaeger:4318/v1/traces

api:
dashboard: false # Change to true for development
debug: true
Expand Down
62 changes: 62 additions & 0 deletions proxy/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
VAULT_DOCKER_IMAGE_NAME ?= ghcr.io/ultravioletrs/vault/proxy
CGO_ENABLED ?= 0
GOOS ?= linux
GOARCH ?= amd64
BUILD_DIR = build
TIME=$(shell date -u '+%Y-%m-%dT%H:%M:%SZ')
VERSION ?= $(shell git describe --abbrev=0 --tags 2>/dev/null || echo 'v0.0.0')
COMMIT ?= $(shell git rev-parse HEAD)

define compile_service
CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) \
go build -ldflags "-s -w \
-X 'github.com/absmach/magistrala.BuildTime=$(TIME)' \
-X 'github.com/absmach/magistrala.Version=$(VERSION)' \
-X 'github.com/absmach/magistrala.Commit=$(COMMIT)'" \
-o ${BUILD_DIR}/vault-proxy cmd/main.go
endef

define make_docker
docker build \
--no-cache \
--build-arg GOOS=$(GOOS) \
--build-arg GOARCH=$(GOARCH) \
--build-arg VERSION=$(VERSION) \
--build-arg COMMIT=$(COMMIT) \
--tag=$(VAULT_DOCKER_IMAGE_NAME):$(VERSION) \
--tag=$(VAULT_DOCKER_IMAGE_NAME):latest \
-f docker/Dockerfile .
endef

define make_docker_dev
docker build \
--no-cache \
--tag=$(VAULT_DOCKER_IMAGE_NAME):$(VERSION) \
--tag=$(VAULT_DOCKER_IMAGE_NAME):latest \
-f docker/Dockerfile.dev ./build
endef

define docker_push
docker push $(VAULT_DOCKER_IMAGE_NAME):$(VERSION)
docker push $(VAULT_DOCKER_IMAGE_NAME):latest
endef

.PHONY: build
build:
$(call compile_service)

.PHONY: docker
docker:
$(call make_docker)

.PHONY: docker-dev
docker-dev:
$(call make_docker_dev)

all: build docker-dev

clean:
rm -rf build

latest: docker
$(call docker_push)
25 changes: 25 additions & 0 deletions proxy/api/endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package api

import (
"context"

"github.com/absmach/magistrala/pkg/apiutil"
"github.com/absmach/magistrala/pkg/errors"
"github.com/go-kit/kit/endpoint"
proxy "github.com/ultraviolet/vault-proxy"
)

func identifyEndpoint(svc proxy.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(identifyRequest)
if err := req.Validate(); err != nil {
return identifyResponse{identified: false}, errors.Wrap(apiutil.ErrValidation, err)
}

if err := svc.Identify(ctx, req.Token); err != nil {
return identifyResponse{identified: false}, err
}

return identifyResponse{identified: true}, nil
}
}
15 changes: 15 additions & 0 deletions proxy/api/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package api

import "github.com/absmach/magistrala/pkg/apiutil"

type identifyRequest struct {
Token string `json:"token"`
}

func (i *identifyRequest) Validate() error {
if i.Token == "" {
return apiutil.ErrBearerToken
}

return nil
}
29 changes: 29 additions & 0 deletions proxy/api/response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package api

import (
"net/http"

"github.com/absmach/magistrala"
)

var _ magistrala.Response = (*identifyResponse)(nil)

type identifyResponse struct {
identified bool
}

func (i *identifyResponse) Code() int {
if i.identified {
return http.StatusOK
}

return http.StatusUnauthorized
}

func (i *identifyResponse) Headers() map[string]string {
return map[string]string{}
}

func (i identifyResponse) Empty() bool {
return true
}
Loading

0 comments on commit b4a4fcb

Please sign in to comment.