Skip to content

Authentication and Authorization


Authenticate requests to the k9 Security API by signing your API request using the AWS SigV4 signing process.

k9's API is serviced by an AWS API Gateway with IAM authentication enabled. When the gateway receives your request, AWS will verify the signature and identify the caller to the API endpoint handlers.

Here are some examples of how to build and sign requests with AWS SigV4 in Python and Golang.

Example - Python

Here is how to construct and sign a trigger account analysis request in Python:

#!/usr/bin/env python3

# adapted from
import requests
from aws_requests_auth.boto_utils import BotoAWSRequestsAuth

api_host = ''
auth = BotoAWSRequestsAuth(aws_host=api_host,

base_url = f'https://{api_host}'

customer_id = "C123456"
account_id = "123456789012"
account_analysis_url = f'{base_url}/customer/{customer_id}/account/{account_id}/analysis'

print(f'triggering account analysis using {account_analysis_url}')
response =,
                         json={"customerId": customer_id, "accountId": account_id},
print(f'status: {response.status_code}')
content = str(response.content, 'UTF-8')

Example - Go

The k9 CLI tool makes the same trigger account analysis request and the code is publicly available on GitHub.

The most important bits are the signAPIRequest and createPayloadHash functions you need to sign the HTTP request:

// Sign a request to the k9 Security AWS API gateway endpoint with an AWS v4 signature
// using the aws-sdk-go-v2 v4.SignHTTP function.
// The request should be fully-built and ready to send to the gateway.
// The provided request will be modified in place.
func signApiRequest(cfg aws.Config, request *http.Request, signingTime time.Time) error {
    ctx := context.TODO()
    credentials, err := cfg.Credentials.Retrieve(ctx)
    if err != nil {
        return err

    hash, err := createPayloadHash(request)
    if err != nil {
        return err

    signer := v4.NewSigner()
    if err != signer.SignHTTP(ctx, credentials, request, hash, "execute-api", cfg.Region, signingTime) {
        return err

    return err

// Create a hex-encoded SHA256 hash of the request payload.  Use when calculating an AWS v4 signature.
func createPayloadHash(req *http.Request) (string, error) {
    // from
    body, err := req.GetBody()
    if err != nil {
        return "", err
    var buf bytes.Buffer
    _, err = buf.ReadFrom(body)
    if err != nil {
        return "", err

    b := sha256.Sum256(buf.Bytes())
    return hex.EncodeToString(b[:]), nil


Once authenticated, the k9 endpoint handlers will authorize the caller's actions. They do that by verifying the API caller ARN is in the set of approved principals for the k9 customer account.

Last update: August 22, 2023