blackey

package module
v0.0.0-...-793c961 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2024 License: MIT Imports: 16 Imported by: 0

README

Blackey: Simple yet Powerful (enough) API Key Management 🔑

Hey there! 👋 Welcome to Blackey, my personal project to solve the headache of API key management. If you're tired of reinventing the wheel for every project, you're in the right place!

What's This All About? 🤔

Ever found yourself coding API key validation over and over? Yeah, me too. That's why I created Blackey. It's a Go module that handles all the API key management stuff, so you can focus on building cool stuff.

What Can Blackey Do? 🚀

  • Generate and validate API keys securely
  • Block requests from unwanted IPs
  • Limit how often an API key can be used (rate limiting)
  • Handle CORS stuff without the hassle
  • Keep track of how your API keys are being used
  • Set up special "root" keys for admin tasks
  • Automatically set up the database tables you need
  • Work smoothly even when lots of people are using your API at once
  • Set usage limits for API keys
  • Make API keys expire after a certain time

How It Works Under the Hood 🛠️

Blackey uses a PostgreSQL database to keep track of everything. Here's a simple breakdown:

  1. One table for API key info
  2. Another for counting how often keys are used
  3. And a third for detailed logs of key usage

It checks IPs, manages rate limits, and handles CORS all in one go. Every time an API key is used, Blackey updates the counts and logs the activity.

Things I'm Still Working On 🚧

  1. Moving the rate limiter to Redis for better performance
  2. Actually implementing the country restriction feature (right now it's just a placeholder)
  3. Making the metrics system work better for super busy APIs
  4. Adding more tests to make sure everything works perfectly

What's Next? 🔮

I've got big plans for Blackey:

  1. Using Redis for even better rate limiting
  2. Adding that country restriction feature using a cool GeoIP database
  3. Making frequently used API keys load faster
  4. Creating a simple web page to manage your API keys
  5. Supporting more database

How to Get Started 🏁

First, grab the code:

go get github.com/ridwankustanto/blackey

Make sure you've got a PostgreSQL database ready. Blackey will set up the tables it needs automatically.

Quick Example 💨

For more example please take alook example directory. Here's a simple way to use Blackey in your project:

package main

import (
    "database/sql"
    "fmt"
    "net/http"

    "github.com/ridwankustanto/blackey"
    _ "github.com/lib/pq"
)

func main() {
    // Connect to your database
    db, err := sql.Open("postgres", "your_connection_string")
    if err != nil {
        panic(err)
    }
    defer db.Close()

    // Set up Blackey
    err := blackey.Initialize(db, "myapi_", 16)
    if err != nil {
        panic(err)
    }

    // Custom error handler example 
    customErrorHandler := func(w http.ResponseWriter, message string, statusCode int) {
		response := map[string]interface{}{
			"error": message,
			"code":  statusCode,
			"data":  nil,
		}
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(statusCode)
		json.NewEncoder(w).Encode(response)
	}

	config := blackey.MiddlewareConfig{
		APIIDHeaderName:  "X-API-Key-ID",
		APIKeyHeaderName: "X-API-Key",
		HeaderPrefix:     "Bearer ",
		ErrorHandler:     customErrorHandler,
	}

    // Your API handler
    // Example implementation of middleware validation and chain middleware
    http.Handle("/api/", logHelloMiddleware(blackey.ValidateAPIKey(config)(yourAPIHandler)))
    // or http.Handle("/api/", blackey.ValidateAPIKey(config)(logHelloMiddleware(http.HandlerFunc(yourAPIHandler))))
    http.Handle("/api/create-key", blackey.IsRootKey(config)(http.HandlerFunc(createAPIKeyHandler)))

    http.ListenAndServe(":8080", nil)
}

func logHelloMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("Hello, World!")
		next.ServeHTTP(w, r)
	})
}

func yourAPIHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hey, your API key works!")
}

On first initialize blackey you will get this message on your terminal,

Blackey initialized successfully. Root ID c157b152-fb12-4e16-b1f3-83e96aa00f09 and Key myapi_8V5SYcmvnDlnMyI-9aWSmA== 
IMPORTANT: Store this root key securely. It will not be shown again. You can check it on the database if needed.

Where Can You Use This? 🌍

Blackey is pretty flexible:

  1. If you're building a SaaS app and need to manage different customer access levels
  2. For securing a public API
  3. 🤔 Hmmmm what else?

Got Ideas or Found a Bug? 🐛

I'd love to hear from you! Here's how you can help:

  1. If you find a problem or idea, open an issue on GitHub

Want to contribute? Awesome!

  1. Fork the repo
  2. Make a new branch for your cool new feature
  3. Commit your changes
  4. Open a pull request and tell me all about what you did

Your help in making Blackey better is super appreciated! 🙌

License

This project is licensed under the MIT License.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrAPIKeyNotFound         = errors.New("API key not found")
	ErrInvalidAPIKey          = errors.New("invalid API key")
	ErrExpiredAPIKey          = errors.New("expired API key")
	ErrLimitUsageExceeded     = errors.New("API key limit usage exceeded")
	ErrRateLimitExceeded      = errors.New("rate limit exceeded")
	ErrInsufficientPrivileges = errors.New("insufficient privileges")
	ErrInvalidAPIKeyID        = errors.New("invalid API key ID format")
	ErrMissingAPIKeyOrID      = errors.New("missing api key or id")
	ErrInternalServerError    = errors.New("internal server error")
	ErrIPNotAllowed           = errors.New("ip not allowed")
	ErrFailedToVerifyRootKey  = errors.New("failed to verify root key")
)
View Source
var ErrUnauthorized = errors.New("unauthorized: invalid root key")

Functions

func ActivateAPIKey

func ActivateAPIKey(keyID string) error

ActivateAPIKey activates a previously revoked API key

func Init

func Init(cfg Config) error

Init initializes the blackey module with the provided configuration

func Initialize

func Initialize(db *sql.DB, prefix string, byteLength int) error

Initialize sets up the necessary tables and generates a root key if not already initialized

func IsRootKey

func IsRootKey(cfg MiddlewareConfig) func(http.Handler) http.Handler

func RevokeAPIKey

func RevokeAPIKey(keyID string) error

RevokeAPIKey revokes an API key

func SetupTables

func SetupTables(db *sql.DB) error

SetupTables creates necessary tables in the database

func UpdateAPIKeyRestrictions

func UpdateAPIKeyRestrictions(keyID string, restrictions APIKey) error

UpdateAPIKeyRestrictions updates the restrictions for an API key

func ValidateAPIKey

func ValidateAPIKey(cfg MiddlewareConfig) func(http.Handler) http.Handler

Types

type APIKey

type APIKey struct {
	ID                 string
	Key                string
	CreatedAt          time.Time
	ExpiresAt          *time.Time
	IsActive           bool
	IsRoot             bool
	AllowedIPs         []string
	AllowedCountries   []string
	CORSAllowedOrigins []string
	RateLimit          *int
	LimitUse           *int
}

APIKey represents an API key in the system

func CreateAPIKey

func CreateAPIKey(restrictions APIKey) (*APIKey, error)

CreateAPIKey creates a new API key

type ActivityLog

type ActivityLog struct {
	ID        string
	APIKeyID  string
	Timestamp time.Time
	UserAgent string
	IPAddress string
	Region    string
}

ActivityLog represents a log entry for API key usage

type Config

type Config struct {
	DB         *sql.DB
	Prefix     string
	ByteLength int
}

Config represents the configuration for the blackey module

type ErrorResponse

type ErrorResponse func(w http.ResponseWriter, message string, statusCode int)

type Metrics

type Metrics struct {
	APIKeyID      string
	ExpiresAt     *time.Time
	RemainingUses *int
	LastUsage     time.Time
	SuccessCount  int
	InvalidCount  int
	TotalAccess   int
}

Metrics represents usage metrics for an API key

func GetMetrics

func GetMetrics(apiKey string) (*Metrics, error)

GetMetrics retrieves usage metrics for an API key

type MiddlewareConfig

type MiddlewareConfig struct {
	APIIDHeaderName  string
	APIKeyHeaderName string
	HeaderPrefix     string
	ErrorHandler     ErrorResponse
}

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

func NewRateLimiter

func NewRateLimiter() *RateLimiter

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL