Skip to content

Authentication and Authorization

Authentication

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 https://github.com/DavidMuller/aws-requests-auth
import requests
from aws_requests_auth.boto_utils import BotoAWSRequestsAuth

api_host = 'api.k9security.io'
auth = BotoAWSRequestsAuth(aws_host=api_host,
                           aws_region='us-east-1',
                           aws_service='execute-api')

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 = requests.post(account_analysis_url,
                         json={"customerId": customer_id, "accountId": account_id},
                         auth=auth,
                         headers={})
print(f'status: {response.status_code}')
content = str(response.content, 'UTF-8')
print(f'content:\n{content}')

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 https://github.com/yuizho/salon/blob/a159bcfeb263cb6502403f682c138286a2d7bb1f/backend/lambda/mutate-user/appsync/client.go
    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
}

Authorization

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: May 20, 2024