Skip to content

Commit

Permalink
Initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewheberle committed Dec 5, 2023
0 parents commit 9eeeef8
Show file tree
Hide file tree
Showing 10 changed files with 1,113 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.exe
Dockerfile
*.crt
*.key
15 changes: 15 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
18 changes: 18 additions & 0 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Docker Image CI

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:

build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Build the Docker image
run: docker build . --file Dockerfile --tag my-image-name:$(date +%s)
98 changes: 98 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
name: Docker

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

on:
schedule:
- cron: '27 23 * * *'
push:
branches: [ "main" ]
# Publish semver tags as releases.
tags: [ 'v*.*.*' ]
pull_request:
branches: [ "main" ]

env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}


jobs:
build:

runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write

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

# Install the cosign tool except on PR
# https://github.com/sigstore/cosign-installer
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 #v3.1.1
with:
cosign-release: 'v2.1.1'

# Set up BuildKit Docker container builder to be able to build
# multi-platform images and export cache
# https://github.com/docker/setup-buildx-action
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0

# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

# Sign the resulting Docker image digest except on PRs.
# This will only write to the public Rekor transparency log when the Docker
# repository is public to avoid leaking data. If you would like to publish
# transparency data even for private images, pass --force to cosign below.
# https://github.com/sigstore/cosign
- name: Sign the published Docker image
if: ${{ github.event_name != 'pull_request' }}
env:
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
TAGS: ${{ steps.meta.outputs.tags }}
DIGEST: ${{ steps.build-and-push.outputs.digest }}
# This step uses the identity token to provision an ephemeral certificate
# against the sigstore community Fulcio instance.
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.exe
*.crt
*.key
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM golang:1.21@sha256:9baee0edab4139ae9b108fffabb8e2e98a67f0b259fd25283c2a084bd74fea0d AS builder

COPY . /build

RUN cd /build && \
go build ./cmd/http-auth-server

FROM gcr.io/distroless/base-debian12:nonroot@sha256:5a779e9c2635dbea68ae7988f398f95686ccde186cd2abf51207e41ed2ec51f4

COPY --from=builder /build/http-auth-server /app/http-auth-server

ENV AUTH_LISTEN=":9091"

ENTRYPOINT [ "/app/http-auth-server" ]
98 changes: 98 additions & 0 deletions cmd/http-auth-server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package main

import (
"log/slog"
"net/http"
"net/url"
"os"
"time"

"github.com/andrewheberle/go-http-auth-server/pkg/sp"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)

func main() {
// command line flags
pflag.String("cert", "", "HTTPS Certificate")
pflag.String("key", "", "HTTPS Key")
pflag.String("listen", "127.0.0.1:9091", "Listen address")
pflag.String("sp-cert", "", "Service Provider Certificate")
pflag.String("sp-key", "", "Service Provider Key")
pflag.String("sp-url", "http://localhost:9091", "Service Provider URL")
pflag.StringToString("sp-claim-mapping", map[string]string{"urn:oasis:names:tc:SAML:attribute:subject-id": "remote-user", "mail": "remote-email", "displayName": "remote-name", "role": "remote-groups"}, "Mapping of claims to headers")
pflag.String("metadata", "", "IdP Metadata URL")
pflag.Bool("debug", false, "Enable debug logging")
pflag.Parse()

// bind to viper
viper.BindPFlags(pflag.CommandLine)

// load from environment
viper.SetEnvPrefix("auth")
viper.AutomaticEnv()

// logging setup
var logLevel = new(slog.LevelVar)
logHandler := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: logLevel})
slog.SetDefault(slog.New(logHandler))
if viper.GetBool("debug") {
logLevel.Set(slog.LevelDebug)
}

// validate service provider root url
root, err := url.Parse(viper.GetString("sp-url"))
if err != nil {
slog.Error("problem with SP URL", err)
os.Exit(1)
}

// validate metadata url
metadata, err := url.Parse(viper.GetString("metadata"))
if err != nil {
slog.Error("problem with IdP metadata URL", err)
os.Exit(1)
}

// set up auth provider
provider, err := sp.NewServiceProvider(viper.GetString("sp-cert"), viper.GetString("sp-key"), metadata, root, viper.GetStringMapString("sp-claim-mapping"))
if err != nil {
slog.Error("problem setting up SP", err)
os.Exit(1)
}

// set up auth endpoints
http.HandleFunc("/api/verify", provider.ForwardAuthHandler)
http.HandleFunc("/api/authz/forward-auth", provider.ForwardAuthHandler)

// set up saml endpoints
http.HandleFunc(provider.AcsURL().Path, provider.ACSHandler)
http.HandleFunc(provider.MetadataURL().Path, provider.MetadataHandler)
http.HandleFunc(provider.LogoutUrl().Path, provider.LogoutHandler)

// login endpoint
http.Handle("/login", provider.RequireAccount(http.HandlerFunc((func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Logged In."))
}))))

// dummy endpoint

srv := &http.Server{
Addr: viper.GetString("listen"),
ReadTimeout: time.Second * 3,
WriteTimeout: time.Second * 3,
}

slog.Info("starting service",
"listen", srv.Addr,
"idp-metadata-url", metadata.String(),
"sp-acs-url", provider.AcsURL().String(),
"sp-metdata-url", provider.MetadataURL().String(),
"sp-logout-url", provider.LogoutUrl().String(),
)

if err := srv.ListenAndServe(); err != nil {
slog.Error("problem with SP URL", err)
os.Exit(1)
}
}
38 changes: 38 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module github.com/andrewheberle/go-http-auth-server

go 1.21.4

require (
github.com/crewjam/saml v0.4.14
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.17.0
)

require (
github.com/beevik/etree v1.1.0 // indirect
github.com/crewjam/httperr v0.2.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/golang-jwt/jwt/v4 v4.4.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/russellhaering/goxmldsig v1.3.0 // indirect
github.com/sagikazarmark/locafero v0.3.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.10.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading

0 comments on commit 9eeeef8

Please sign in to comment.