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.