Skip to content

Commit

Permalink
Merge pull request #67 from mchurichi/simple-demo
Browse files Browse the repository at this point in the history
Adds simple demo script
  • Loading branch information
mchurichi authored Oct 31, 2022
2 parents 78c1f71 + 094cdb4 commit 477379b
Show file tree
Hide file tree
Showing 28 changed files with 670 additions and 15 deletions.
32 changes: 32 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# golang:1.19.2-alpine3.16
ARG builderimage=golang@sha256:46752c2ee3bd8388608e41362964c84f7a6dffe99d86faeddc82d917740c5968
# alpine:3.16.2
ARG baseimage=alpine@sha256:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870

# Build stage
FROM ${builderimage} as builder
RUN apk add build-base ncurses curl
ADD go.mod /galadriel/go.mod
WORKDIR /galadriel
RUN go mod download
ADD . /galadriel/
RUN make build

# Base image
FROM ${baseimage} AS base
RUN apk --no-cache add dumb-init
RUN mkdir -p /opt/galadriel/bin

# Galadriel Server
FROM base AS galadriel-server
COPY --from=builder /galadriel/bin/galadriel-server /opt/galadriel/bin/galadriel-server
WORKDIR /opt/galadriel
ENTRYPOINT ["/usr/bin/dumb-init", "/opt/galadriel/bin/galadriel-server"]
CMD ["run"]

# Galadriel Harvester
FROM base AS galadriel-harvester
COPY --from=builder /galadriel/bin/galadriel-harvester /opt/galadriel/bin/galadriel-harvester
WORKDIR /opt/galadriel
ENTRYPOINT ["/usr/bin/dumb-init", "/opt/galadriel/bin/galadriel-harvester"]
CMD ["run"]
30 changes: 15 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ space := $(null)

.PHONY: build

## Compile Go binaries for the Galadriel.
## Compiles all Galadriel binaries.
build: bin/galadriel-harvester bin/galadriel-server

# This is the master template for compiling Go binaries
Expand All @@ -121,33 +121,33 @@ CONTAINER_EXEC := $(foreach exec,$(CONTAINER_OPTIONS),\
server-run: build
./bin/galadriel-server run

api-doc-build:
$(CONTAINER_EXEC) build -f doc/api/Dockerfile -t galadriel-api-doc:latest .

## Build the API documentation for the Galadriel.
api-doc: api-doc-build
$(CONTAINER_EXEC) run --rm \
--name galadriel-api-doc \
-p 8000:8000 \
--mount type=bind,source=${DIR}/spec/api,target=/app/api,readonly \
galadriel-api-doc:latest

## Runs the go unit tests.
test: test-unit

test-unit:
go test -cover ./...

## Run unit tests with race detection.
## Runs unit tests with race detection.
race-test:
go test -cover -race ./...

## Generate the test coverage for the code with the Go tool.
## Generates the test coverage for the code with the Go tool.
coverage:
$(E)mkdir -p out/coverage
go test -v -coverprofile ./out/coverage/coverage.out ./... && \
go tool cover -html=./out/coverage/coverage.out -o ./out/coverage/index.html

## Builds docker image for Galadriel Server.
docker-build-server:
docker build . --target galadriel-server --tag galadriel-server:latest

## Builds docker image for Galadriel Harvester.
docker-build-harvester:
docker build . --target galadriel-harvester --tag galadriel-harvester:latest

## Builds all docker images.
docker-build: docker-build-server docker-build-harvester

#------------------------------------------------------------------------
# Document file
#------------------------------------------------------------------------
Expand All @@ -161,7 +161,7 @@ AUTHOR=HPE
GREEN := $(shell tput -Txterm setaf 2)
RESET := $(shell tput -Txterm sgr0)

TARGET_MAX_CHAR_NUM=20
TARGET_MAX_CHAR_NUM=30

## Shows help.
help:
Expand Down
1 change: 1 addition & 0 deletions cmd/harvester/cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func LoadConfig(cmd *cobra.Command) (*harvester.Config, error) {
}

logrus.SetLevel(logLevel)
logrus.SetOutput(os.Stdout)

hc.AccessToken = token

Expand Down
2 changes: 2 additions & 0 deletions cmd/server/cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ func LoadConfig(cmd *cobra.Command) (*server.Config, error) {
if err != nil {
return nil, err
}

logrus.SetLevel(logLevel)
logrus.SetOutput(os.Stdout)

return sc, nil
}
Expand Down
3 changes: 3 additions & 0 deletions demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**/spire/.data
**/spire/conf/agent/root_ca.crt
bin/
31 changes: 31 additions & 0 deletions demo/0-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
set -e

SPIRE_VERSION=${SPIRE_VERSION:=v1.4.4}

cwd=$(pwd)
temp_clone=/tmp/spire-${SPIRE_VERSION}
mkdir -p ./bin

cleanup() {
rm -rf ${temp_clone}
exit
}
trap cleanup EXIT

# Build SPIRE
git clone https://github.com/spiffe/spire.git --single-branch --branch ${SPIRE_VERSION} -c advice.detachedHead=false ${temp_clone}
(cd ${temp_clone}; \
make build; \
cp bin/spire-server bin/spire-agent ${cwd}/bin/)

# Build Galadriel
(cd ../; \
make build; \
cp ./bin/galadriel-server ./bin/galadriel-harvester ${cwd}/bin/)

# Build greeter demo
(cd greeter; \
CGO_ENABLED=0 go build -o ../bin/greeter-server ./cmd/greeter-server/main.go;
CGO_ENABLED=0 go build -o ../bin/greeter-client ./cmd/greeter-client/main.go)

8 changes: 8 additions & 0 deletions demo/1-run-spire-servers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
set -e
source util.sh

one ./bin/spire-server run -config one.org/spire/conf/server/server.conf
two ./bin/spire-server run -config two.org/spire/conf/server/server.conf

wait
20 changes: 20 additions & 0 deletions demo/2-run-spire-agents.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash
set -e
source util.sh

spire_one_socket=/tmp/one.org/spire-server/private/api.sock
spire_two_socket=/tmp/two.org/spire-server/private/api.sock

# Get current CA from SPIRE Server
./bin/spire-server bundle show -socketPath ${spire_one_socket} > ./one.org/spire/conf/agent/root_ca.crt
./bin/spire-server bundle show -socketPath ${spire_two_socket} > ./two.org/spire/conf/agent/root_ca.crt

# Get join tokens
token_one=$(./bin/spire-server token generate -socketPath ${spire_one_socket} -spiffeID spiffe://one.org/my-agent | grep Token | cut -c 8-100)
token_two=$(./bin/spire-server token generate -socketPath ${spire_two_socket} -spiffeID spiffe://two.org/my-agent | grep Token | cut -c 8-100)

# Start agents
one ./bin/spire-agent run -config ./one.org/spire/conf/agent/agent.conf -joinToken ${token_one}
two ./bin/spire-agent run -config ./two.org/spire/conf/agent/agent.conf -joinToken ${token_two}

wait
5 changes: 5 additions & 0 deletions demo/3-run-galadriel-server.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash
set -e

# Run Galadriel Server
./bin/galadriel-server run --config ./galadriel-server/server.conf
6 changes: 6 additions & 0 deletions demo/4-create-members.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash
set -e

./bin/galadriel-server create member --trustDomain one.org
./bin/galadriel-server create member --trustDomain two.org
./bin/galadriel-server create relationship -a one.org -b two.org
11 changes: 11 additions & 0 deletions demo/5-run-harvesters.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash
set -e
source util.sh

token_one=$(./bin/galadriel-server generate token -t one.org | cut -c 15-100)
token_two=$(./bin/galadriel-server generate token -t two.org | cut -c 15-100)

one ./bin/galadriel-harvester run --config ./one.org/harvester/harvester.conf --token ${token_one}
two ./bin/galadriel-harvester run --config ./two.org/harvester/harvester.conf --token ${token_two}

wait
21 changes: 21 additions & 0 deletions demo/6-create-entries.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash
set -e

spire_one_socket=/tmp/one.org/spire-server/private/api.sock
spire_two_socket=/tmp/two.org/spire-server/private/api.sock

# Create entry for greeter-server in one.org
./bin/spire-server entry create \
-socketPath ${spire_one_socket} \
-spiffeID spiffe://one.org/greeter-server \
-parentID spiffe://one.org/my-agent \
-selector unix:uid:$(id -u) \
-federatesWith two.org

# Create entry for greeter-client in two.org
./bin/spire-server entry create \
-socketPath ${spire_two_socket} \
-spiffeID spiffe://two.org/greeter-client \
-parentID spiffe://two.org/my-agent \
-selector unix:uid:$(id -u) \
-federatesWith one.org
17 changes: 17 additions & 0 deletions demo/7-run-greeter.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
set -e
source util.sh

agent_one_socket=/tmp/one.org/spire-agent/private/api.sock
agent_two_socket=/tmp/two.org/spire-agent/private/api.sock

cleanup() {
pkill greeter-server greeter-client
}
trap cleanup EXIT

# Run greeter server and client
server ./bin/greeter-server --workloadapi unix://${agent_one_socket}; sleep 5
client ./bin/greeter-client --workloadapi unix://${agent_two_socket}

wait
32 changes: 32 additions & 0 deletions demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Demo

The following demo script shows how to setup two simple SPIRE deployments and have them federated using Galadriel.

![Demo diagram](diagram.png "Demo diagram")

## Requirements

This demo only requires a `git` client and the `make` command properly installed in the system.

Tested on macOS Mojave and Ventura, and Debian Bullseye.

## Steps

Run the following scripts in order:

- `0-setup.sh`: This will make sure you have all SPIRE, Galadriel and the sample application binaries.
- `1-run-spire-servers.sh`: Runs two SPIRE Server instances, `one.org` and `two.org`.
- `2-run-spire-agents.sh`: Runs and attests two SPIRE Agent instances using join tokens.
- `3-run-galadriel-server.sh`: Runs an instance of the Galadriel Server.
- `4-create-members.sh`: Creates the member entities for both Trust Domains in Galadriel, and setups a federation relationship between them.
- `5-run-harvester.sh`: Runs two Galadriel Harvesters connected to the Galadriel Server and to each SPIRE Server.
- `6-create-entries.sh`: Creates the federated entries needed to attest the sample `greeter` application server and client.
- `7-run-greeter.sh`: Runs the greeter server and client.

The `greeter` server fetches its SVID from the SPIRE Agent serving `one.org`, and uses this credential to listen for incoming connections.

The `greeter` client fetches its SVID from the SPIRE Agent serving `two.org`, and uses this credential to connect to the server.

## Cleanup

Run `x-cleanup.sh` to remove from the system all the SPIRE data created by this demo.
Binary file added demo/diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions demo/galadriel-server/server.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
server {
listen_address = "localhost"
listen_port = "8085"
socket_path = "/tmp/galadriel-server/api.sock"
}
79 changes: 79 additions & 0 deletions demo/greeter/cmd/greeter-client/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package main

import (
"context"
"flag"
"log"
"os"
"time"

"github.com/spiffe/go-spiffe/v2/spiffegrpc/grpccredentials"
"github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig"
"github.com/spiffe/go-spiffe/v2/workloadapi"
"google.golang.org/grpc"
"google.golang.org/grpc/examples/helloworld/helloworld"
"google.golang.org/grpc/peer"
)

func main() {
var serverAddr string
var wlapiAddr string

flag.StringVar(&serverAddr, "server", "localhost:8080", "host:port of the server")
flag.StringVar(&wlapiAddr, "workloadapi", "unix:///tmp/spire-agent/public/api.sock", "workload endpoint socket URI, starting with tcp:// or unix:// scheme")
flag.Parse()

log.SetOutput(os.Stdout)
log.Println("Starting up...")
log.Println("Server Address:", serverAddr)

ctx := context.Background()

// Get credentials from the Workload API
log.Println("Calling Workload API...")
timeoutCtx, cancel := context.WithTimeout(ctx, time.Second*5)
defer cancel()

opts := workloadapi.WithClientOptions(workloadapi.WithAddr(wlapiAddr))
source, err := workloadapi.NewX509Source(timeoutCtx, opts)
if err != nil {
log.Fatal(err)
}
defer source.Close()
creds := grpccredentials.MTLSClientCredentials(source, source, tlsconfig.AuthorizeAny())

// Establish gRPC connection to the server
client, err := grpc.DialContext(timeoutCtx, serverAddr, grpc.WithTransportCredentials(creds))
if err != nil {
log.Fatal(err)
}
defer client.Close()

// Make calls to the greeter server
greeterClient := helloworld.NewGreeterClient(client)

const interval = time.Second * 10
log.Printf("Issuing requests every %s...", interval)
for {
issueRequest(ctx, greeterClient)
time.Sleep(interval)
}
}

func issueRequest(ctx context.Context, c helloworld.GreeterClient) {
p := new(peer.Peer)
resp, err := c.SayHello(ctx, &helloworld.HelloRequest{
Name: "SPIFFE community",
}, grpc.Peer(p))
if err != nil {
log.Printf("Failed to say hello: %v", err)
return
}

serverID := "UNKNOWN-SERVER"
if peerID, ok := grpccredentials.PeerIDFromPeer(p); ok {
serverID = peerID.String()
}

log.Printf("%s said %q", serverID, resp.Message)
}
Loading

0 comments on commit 477379b

Please sign in to comment.