{"id":16188985,"url":"https://github.com/fogfish/scud","last_synced_at":"2025-07-21T10:34:04.979Z","repository":{"id":37849114,"uuid":"320860264","full_name":"fogfish/scud","owner":"fogfish","description":"Simplified Serverless API Gateway (AWS CDK L3)","archived":false,"fork":false,"pushed_at":"2025-07-06T19:25:47.000Z","size":1824,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-06T20:34:11.934Z","etag":null,"topics":["aws-api-gateway","aws-cdk","aws-cdk-construct","aws-cdk-go","aws-lambda","golang","golang-serverless","serverless"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fogfish.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-12-12T15:21:50.000Z","updated_at":"2025-07-06T19:25:15.000Z","dependencies_parsed_at":"2024-03-14T23:24:08.912Z","dependency_job_id":"f079f58d-5f99-4bd6-a792-37b13229c38c","html_url":"https://github.com/fogfish/scud","commit_stats":{"total_commits":61,"total_committers":1,"mean_commits":61.0,"dds":0.0,"last_synced_commit":"aafdd6126f1d4bea1b13e6667625fc0c67d0a77b"},"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"purl":"pkg:github/fogfish/scud","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fscud","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fscud/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fscud/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fscud/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fogfish","download_url":"https://codeload.github.com/fogfish/scud/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fogfish%2Fscud/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266285572,"owners_count":23905382,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws-api-gateway","aws-cdk","aws-cdk-construct","aws-cdk-go","aws-lambda","golang","golang-serverless","serverless"],"created_at":"2024-10-10T07:33:07.643Z","updated_at":"2025-07-21T10:34:04.972Z","avatar_url":"https://github.com/fogfish.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./doc/scud-logo.png\" height=\"240\" /\u003e\n  \u003ch3 align=\"center\"\u003escud\u003c/h3\u003e\n  \u003cp align=\"center\"\u003e\u003cstrong\u003eserverless Golang made simple, secure, and fast\u003c/strong\u003e\u003c/p\u003e\n\n  \u003cp align=\"center\"\u003e\n    \u003c!-- Version --\u003e\n    \u003ca href=\"https://github.com/fogfish/scud/releases\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/v/tag/fogfish/scud?label=version\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Documentation --\u003e\n    \u003ca href=\"https://pkg.go.dev/github.com/fogfish/scud\"\u003e\n      \u003cimg src=\"https://pkg.go.dev/badge/github.com/fogfish/scud\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Build Status  --\u003e\n    \u003ca href=\"https://github.com/fogfish/scud/actions/\"\u003e\n      \u003cimg src=\"https://github.com/fogfish/scud/workflows/build/badge.svg\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- GitHub --\u003e\n    \u003ca href=\"http://github.com/fogfish/scud\"\u003e\n      \u003cimg src=\"https://img.shields.io/github/last-commit/fogfish/scud.svg\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Coverage --\u003e\n    \u003ca href=\"https://coveralls.io/github/fogfish/scud?branch=main\"\u003e\n      \u003cimg src=\"https://coveralls.io/repos/github/fogfish/scud/badge.svg?branch=main\" /\u003e\n    \u003c/a\u003e\n    \u003c!-- Go Card --\u003e\n    \u003ca href=\"https://goreportcard.com/report/github.com/fogfish/scud\"\u003e\n      \u003cimg src=\"https://goreportcard.com/badge/github.com/fogfish/scud\" /\u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n--- \n\n`scud` (Serverless Configuration \u0026 Utilities for Deployment) is a developer-friendly toolkit for building and deploying secure serverless Golang APIs on AWS.\n\nIt simplifies the process of compiling Golang serverless functions as an integral part of the AWS CDK workflow. The resulting Lambda functions are directly consumable by both standard and third-party AWS CDK constructs.\n\nSCUD also provides an AWS CDK L3 construct for API Gateway that takes care of the infrastructure boilerplate required for secure serverless RESTful API development.\n\nWith SCUD, you can deliver fast, secure, and maintainable serverless APIs without the boilerplate.\n\n- [Getting started](#getting-started)\n- [Quick Start](#quick-start)\n- [Golang Serverless](#golang-serverless)\n  - [Linker Flags and Version Injection](#linker-flags-and-version-injection)\n  - [Lambda Environment Variables](#lambda-environment-variables)\n  - [Architecture: Graviton vs x86\\_64](#architecture-graviton-vs-x86_64)\n  - [Container images](#container-images)\n  - [Universal Function](#universal-function)\n  - [Custom Go Environment](#custom-go-environment)\n  - [Logging](#logging)\n  - [Compressing binaries](#compressing-binaries)\n- [API Gateway](#api-gateway)\n  - [Quick Start](#quick-start-1)\n  - [API Gateway](#api-gateway-1)\n  - [API Gateway (Domain Name)](#api-gateway-domain-name)\n  - [API Gateway (Resources)](#api-gateway-resources)\n  - [Authorizer IAM](#authorizer-iam)\n  - [Authorizer AWS Cognito](#authorizer-aws-cognito)\n  - [Authorizer JWT](#authorizer-jwt)\n- [HowTo Contribute](#howto-contribute)\n- [License](#license)\n- [References](#references)\n\n\n## Getting started\n\nThe latest version of the library is available at its `main` branch. All development, including new features and bug fixes, take place on the `main` branch using forking and pull requests as described in contribution guidelines. The stable version is available via Golang modules.\n\nUse `go get` to retrieve the library and add it as dependency to your application.\n\n```bash\ngo get -u github.com/fogfish/scud\n```\n\n## Quick Start\n\nBelow is a minimal example of deploying a Golang application to AWS Lambda. The key feature here is that the compilation, packaging, and deployment of the function are fully integrated into the `cdk deploy` workflow.\n\n```go\npackage main\n\nimport (\n  \"github.com/aws/aws-cdk-go/awscdk/v2\"\n  \"github.com/aws/jsii-runtime-go\"\n  \"github.com/fogfish/scud\"\n)\n\nfunc main() {\n  app := awscdk.NewApp(nil)\n  stack := awscdk.NewStack(app, jsii.String(\"example\"), nil)\n\n  scud.NewFunctionGo(stack, jsii.String(\"MyFun\"),\n    \u0026scud.FunctionGoProps{\n      SourceCodeModule: \"github.com/fogfish/scud\",\n      SourceCodeLambda: \"examples/01_simple_function/lambda\",\n    },\n  )\n\n  app.Synth(nil)\n}\n```\n\n## Golang Serverless\n\nAWS CDK has a bundling feature that simplify the process of creating assets for Lambda functions from source code. This feature is useful for compiling and packaging Golang executable binaries into AWS Lambda assets. `scud` implements L3 construct to bundle Golang source code into ARM64 lambdas for Amazon Linux 2 requiring no effort that running `cdk deploy`.\n\n```go\nscud.NewFunctionGo(stack, jsii.String(\"Handler\"),\n  \u0026scud.FunctionGoProps{\n    // Golang module that containing the function\n    SourceCodeModule: \"github.com/fogfish/scud\",\n    // Path to lambda function within the module \n    SourceCodeLambda:  \"test/lambda/go\",\n    // Lambda properties\n    FunctionProps: \u0026awslambda.FunctionProps{},\n  },\n)\n```\n\nThe benefit of using this L3 construct is its **optimized deployment strategy**, designed for monorepos that contain many Lambda functions. It automatically detects changes in the source code and deploys **only the Lambda functions that have been modified**, instead of redeploying everything. This makes deployments faster and more efficient, especially in large projects.\n\n\n### Linker Flags and Version Injection\n\nYou can inject custom variables and version information into your Go Lambda binary using the `GoVar` and `SourceCodeVersion` properties. These are passed as `-ldflags` to the Go compiler.\n\n```go\nscud.NewFunctionGo(stack, jsii.String(\"Handler\"),\n  \u0026scud.FunctionGoProps{\n    SourceCodeModule: \"github.com/fogfish/scud\",\n    SourceCodeLambda: \"test/lambda/go\",\n    SourceCodeVersion: \"v1.2.3\", // Injects -X main.version=v1.2.3\n    GoVar: map[string]string{\n      \"main.buildTime\": \"2024-01-01\",  // Injects -X main.buildTime=2024-01-01\n      \"main.commit\":    \"abc123\",      // Injects -X main.commit=abc123\n    },\n  },\n)\n```\n\nThis allows you to access version and build information in your Lambda function:\n\n```go\npackage main\n\nvar (\n    version   = \"dev\"\n    buildTime = \"unknown\" \n    commit    = \"unknown\"\n)\n\nfunc main() {\n    log.Printf(\"Version: %s, Build: %s, Commit: %s\", version, buildTime, commit)\n    // ... rest of your Lambda code\n}\n```\n\n### Lambda Environment Variables\n\nUse `awslambda.Function` and its `AddEnvironment` method to set runtime environment variables for your Lambda function:\n\n```go\nf := scud.NewFunctionGo(stack, jsii.String(\"Handler\"),\n  \u0026scud.FunctionGoProps{\n    SourceCodeModule: \"github.com/fogfish/scud\",\n    SourceCodeLambda: \"test/lambda/go\",\n  }\n)\n\n// Set environment variables for the Lambda function\nf.AddEnvironment(jsii.String(\"DATABASE_URL\"), jsii.String(\"postgresql://...\"), nil)\nf.AddEnvironment(jsii.String(\"LOG_LEVEL\"), jsii.String(\"debug\"), nil)\n```\n\n\n### Architecture: Graviton vs x86_64\n\nGraviton (ARM64) is default architecture for lambda function supported by the library. Use standard Golang environment variable `\"GOARCH\"` to change the default architecture. Pass environment variable using `GoEnv` property:\n\n```go\nscud.NewFunctionGo(scope, jsii.String(\"test\"),\n  \u0026scud.FunctionGoProps{\n    SourceCodeModule: \"github.com/fogfish/scud\",\n    SourceCodeLambda:  \"test/lambda/go\",\n    GoEnv: map[string]string{\"GOARCH\": \"amd64\"},\n  },\n)\n```\n\n\n### Container images\n\nBy default, Lambda functions are distributed as ZIP files. The library also supports building and deploying Lambda functions from containers. The provided L3 construct reduces the boilerplate required to define and build such containers, offering a simpler interface compared to the standard AWS CDK `DockerImageCode.fromImageAsset`. It allows you to easily package your executable, include static assets, and install any required packages.\n\nThe resulting container is based on either scratch if your code is pure Golang, or Linux Alpine if additional system packages are specified.\n\n```go\nscud.NewContainerGo(stack, jsii.String(\"test\"),\n  \u0026scud.ContainerGoProps{\n    SourceCodeModule: \"github.com/fogfish/scud\",\n    SourceCodeLambda: \"test/lambda/go\",\n    StaticAssets: []string{\n      // list of files to be include into container\n      // path is relative to SourceCodeModule\n      // For example \n      \"test/lambda/go/main.go\"\n    },\n    Packages: []string{\n      // Additional Linux packages to install\n      \"zip\", \"curl\",\n    },\n  },\n)\n```\n\n### Universal Function\n\nFor dynamic function creation, you can use the universal `NewFunction` constructor that accepts either `FunctionGoProps` or `ContainerGoProps`:\n\n```go\n// Works with FunctionGoProps\nfunc1 := scud.NewFunction(stack, jsii.String(\"func1\"),\n  \u0026scud.FunctionGoProps{\n    SourceCodeModule: \"github.com/fogfish/scud\",\n    SourceCodeLambda: \"test/lambda/go\",\n  },\n)\n\n// Works with ContainerGoProps  \nfunc2 := scud.NewFunction(stack, jsii.String(\"func2\"),\n  \u0026scud.ContainerGoProps{\n    SourceCodeModule: \"github.com/fogfish/scud\",\n    SourceCodeLambda: \"test/lambda/go\",\n  },\n)\n```\n\n### Custom Go Environment\n\nYou can set additional Go environment variables for the build process using the `GoEnv` property. The library sets sensible defaults, but you can override them:\n\n```go\nscud.NewFunctionGo(stack, jsii.String(\"Handler\"),\n  \u0026scud.FunctionGoProps{\n    SourceCodeModule: \"github.com/fogfish/scud\",\n    SourceCodeLambda: \"test/lambda/go\",\n    GoEnv: map[string]string{\n      \"GOARCH\":      \"amd64\",           // Override architecture\n      \"CGO_ENABLED\": \"1\",               // Enable CGO if needed\n      \"GOCACHE\":     \"/tmp/go-build\",   // Custom build cache\n    },\n  },\n)\n```\n\nDefault environment variables set by the library:\n- `GOOS=linux`\n- `GOARCH=arm64` \n- `CGO_ENABLED=0`\n\n\n### Logging\n\nThe L3 construct automatically creates a log group if one is not specified. It is recommended to define a single log group per application and reuse it across all Lambda functions.\n\n\u003e For example, you could use a single log group to store logs for all of the Lambda functions that make up a particular application. \n- https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs-loggroups.html\n\n### Compressing binaries\n\nThe L3 constuct uses the `-s` and `-w` linker flags by default to strip the debugging information from binaries. If you have [UPX](https://upx.github.io/) installed, you can enable binary compression by setting the `SCUD_COMPRESS_UPX=1` environment variable before deploying the application. This can significantly reduce the size (almost 7x smaller) of your Lambda deployment package:\n\n```bash\nexport SCUD_COMPRESS_UPX=1\ncdk synth\n```\n\nThe compression uses UPX with the `--best --lzma` flags for maximum compression.\nSee more about compressions:\n* https://words.filippo.io/shrink-your-go-binaries-with-this-one-weird-trick/\n* https://sibprogrammer.medium.com/go-binary-optimization-tricks-648673cc64ac\n\n\n## API Gateway\n\nAWS API Gateway and AWS Lambda are a perfect approach for quick prototyping or production development of microservices on Amazon Web Services. Unfortunately, it requires a significant amount of boilerplate AWS CDK code to bootstrap the development. The `scud` library implements high-order components on top of AWS CDK that harden the API pattern including built-in validation of OAuth2 Bearer tokens for each API endpoint, supporting various identity providers such as IAM, JWT tokens, and AWS Cognito.\n\n![RESTful API Pattern](./doc/scud.excalidraw.svg \"RESTful API Pattern\")\n\n### Quick Start\n\n```go\npackage main\n\nimport (\n  \"github.com/aws/aws-cdk-go/awscdk/v2\"\n  \"github.com/aws/aws-cdk-go/awscdk/v2/awsapigatewayv2\"\n  \"github.com/aws/jsii-runtime-go\"\n  \"github.com/fogfish/scud\"\n)\n\nfunc main() {\n  app := awscdk.NewApp(nil)\n  stack := awscdk.NewStack(app, jsii.String(\"example-api\"), nil)\n\n  // API Gateway\n  api := scud.NewGateway(stack, jsii.String(\"Gateway\"), \u0026scud.GatewayProps{})\n\n  // Handler Function\n  fun := scud.NewFunctionGo(stack, jsii.String(\"Handler\"),\n    \u0026scud.FunctionGoProps{\n      SourceCodeModule: \"github.com/fogfish/scud\",\n      SourceCodeLambda:  \"test/lambda/go\",\n    },\n  )\n\n  // Example endpoint\n  api.AddResource(\"/example\", fun)\n\n  app.Synth(nil)\n}\n```\n\n### API Gateway \n\nThe library defined presets for AWS API Gateway V2. \n\n```go\nscud.NewGateway(stack, jsii.String(\"Gateway\"),\n  \u0026scud.GatewayProps{}\n)\n```\n\n### API Gateway (Domain Name)\n\nThe library deploy gateway using default AWS host naming convention `https://{uid}.execute-api.{region}.amazonaws.com`. Supply custom domain name and Certificate ARN for custom naming.\n\n```go\nscud.NewGateway(stack, jsii.String(\"Gateway\"),\n  \u0026scud.GatewayProps{\n    Host: jsii.String(\"test.example.com\"),\n    TlsArn: jsii.String(\"arn:aws:acm:eu-west-1:000000000000:certificate/00000000-0000-0000-0000-000000000000\"),\n  },\n)\n```\n\n### API Gateway (Resources)\n\nThe Gateway construct implements the `AddResource` function to associate a Lambda function with a REST API path. It uses the specified path as a prefix, enabling the association of the Lambda function with all subpaths under that prefix. \n\n```go\ngateway.AddResource(\"/example\", handler)\n```\n\n### Authorizer IAM\n\nThe library supports integration with AWS IAM to authorize incoming requests. This integration ensures that only authenticated and authorized principals  can access the resources and functionalities provided by your Lambda functions. By leveraging AWS IAM policies and roles, the library enforces fine-grained access control, enhancing the security of your API endpoints.\n\n```go\napi := scud.NewGateway(stack, jsii.String(\"Gateway\"),\n  \u0026scud.GatewayProps{}\n)\n\n// Using the IAM authorizer requires specifying a principal or role. \nrole := awsiam.NewRole(/* ... */)\n\napi.NewAuthorizerIAM().\n  AddResource(\"/example\", handler, role)\n```\n\nYou can still access API with curl even with IAM authorizer is used.\n\n```bash\ncurl https://example.com/petshop/pets \\\n  -XGET \\\n  -H \"Accept: application/json\" \\\n  -H \"x-amz-security-token: $AWS_SESSION_TOKEN\" \\\n  --aws-sigv4 \"aws:amz:eu-west-1:execute-api\" \\\n  --user \"$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY\"\n```\n\n### Authorizer AWS Cognito\n\nThe library supports integration with AWS Cognito to authorize incoming requests. This integration allows you to manage user authentication and authorization seamlessly. By utilizing AWS Cognito, you can implement robust user sign-up, sign-in, and access control mechanisms. The library ensures that only authenticated users with valid tokens can access your API endpoints, providing an additional layer of security and user management capabilities. The integration of AWS API Gateway and AWS Cognito is well documented in [the official documentation](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html). This pattern facilitates the deployment of this configuration by simply providing the ARN of the user pool and specifying scopes to protect your endpoints.\n\n```go\napi := scud.NewGateway(stack, jsii.String(\"Gateway\"),\n  \u0026scud.GatewayProps{}\n)\n\n// Cognito pool has to be pre-defined.\n// Supply list of allowed clients to control the access.\napi.NewAuthorizerCognito(\"arn:aws:cognito-idp:...\", /* ... */).\n  AddResource(\"/example\", handler, \"my/scope\")\n```\n\n### Authorizer JWT\n\nThe library supports integration with Single Sign On provider (e.g. Auth0) to authorize incoming requests using JWT tokens. This integration allows you to leverage external identity providers for user authentication, ensuring secure and seamless access to your API endpoints. By validating JWT tokens issued by the SSO provider, the library ensures that only authenticated users can access your resources. Additionally, this setup can support various SSO standards and providers, enhancing flexibility and security in managing user identities and permissions.\n\n```go\napi := scud.NewGateway(stack, jsii.String(\"Gateway\"),\n  \u0026scud.GatewayProps{}\n)\n\napi.NewAuthorizerJwt(\"https://{tenant}.eu.auth0.com/\", \"https://example.com\").\n  AddResource(\"/example\", handler, \"my/scope\")\n```\n\n## HowTo Contribute\n\nThe project is [MIT](https://github.com/fogfish/scud/blob/master/LICENSE) licensed and accepts contributions via GitHub pull requests:\n\n1. Fork it and clone \n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Added some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n\n```bash\ngit clone https://github.com/fogfish/scud\ncd scud\n\ngo build\ngo test\n```\n\n## License\n\n[![See LICENSE](https://img.shields.io/github/license/fogfish/scud.svg?style=for-the-badge)](LICENSE)\n\n## References\n\n1. [Migrating AWS Lambda functions from the Go1.x runtime to the custom runtime on Amazon Linux 2](https://aws.amazon.com/blogs/compute/migrating-aws-lambda-functions-from-the-go1-x-runtime-to-the-custom-runtime-on-amazon-linux-2/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffogfish%2Fscud","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffogfish%2Fscud","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffogfish%2Fscud/lists"}