Deploying Leonidas
There are two supported options for deploying the Leonidas API:
- Deploying the CI/CD pipeline into AWS, then letting that generate and deploy the API
- Generating and running it locally
The former is recommended for production, as it provides a stronger security model (such as the built-in API key authentication on the API gateway deployed as part of the API). The latter is best suited for development purposes.
Deploying Leonidas to AWS
There are two parts to deploying Leonidas. First, the pipeline is created, then the API deployed.
Deploying the Pipeline
The simplest and most reliable way to run the Leonidas API is via the CI/CD pipeline. This is deployed as follows:
- Install Terraform 0.12+ - https://www.terraform.io/downloads.html
cd aws-pipeline
- Modify
provider.tf
- Set the region you wish to deploy the pipeline into
- Remove the
terraform
block if not using S3 remote state. If it is desired, configure for your own S3 bucket - Set the AWS CLI profile name to use in the
profile
fields
- Run
terraform init
to instantiate the providers - Run
terraform plan
to ensure no syntax errors as a result of the above edit - Run
terraform apply
to deploy the pipeline
Building and Deploying the API
Once Leonidas is deployed, push the code up to the repository.
cd ./aws-pipeline
terraform output repo
, take theclone_url_ssh
terraform output ssh_config
, take theUser
- Merge the two outputs into a single URL, the final URL should be of the format
ssh://USER@git-codecommit....
whereUSER@
is added just after thessh://
of theclone_url_ssh
- Add the new CodeCommit repository URL as a remote -
git remote add pipeline [URL]
- Modify
generator/config.yml
to set the region into which you wish to deploy the API git push pipeline master
- Wait for the pipeline to deploy Leonidas, you can track this in the CodePipeline interface in the AWS GUI. It should only take a few minutes
- Get the rest API id by running
aws apigateway get-rest-apis | jq -r .items[].id
- The URL will be
https://[API-ID].execute-api.[REGION].amazonaws.com/dev/
To allow others to deploy updates and new test cases to this Leonidas instance, create an IAM user for each of them, add an SSH key to the IAM user, and add the user to the codecommit_group
IAM group.
Generating an IAM Policy for the API
The API is deployed with an appropriate role and policy for the test cases defined. Should you wish to deploy roles into other accounts for the Leonidas API to assume, it is possible to generate the JSON document needed to create a suitable IAM policy with the following command:
poetry run ./generator.py iam-policy
Removing Leonidas from an AWS account
- Install the serverless framework locally
- Change directory into
generator/
poetry install
serverless plugin install --name serverless-python-requirements
serverless plugin install --name serverless-wsgi
poetry run ./generator.py serverless-config > serverless.yml
sls remove
- Change directory into
aws-pipeline/
terraform destroy
- Check both the intended deployment region and us-east-1 for lingering S3 buckets, as the AWS API will not allow deletion of non-empty buckets. This can instead be done through the console.
Deploying Leonidas in a Kubernetes Cluster
Leonidas can be deployed as a containerised application within a pod in an existing Kubernetes cluster. On a high level, this includes generating the Python API from the definitions, packaging the code into a container image and pushing it to a repository, which can then be pulled into a Kubernetes pod as part of the Leonidas Kubernetes resources deployed within the cluster. All these steps can be carried out using the generator utility.
It is recommended that ephemeral images are used for the Leonidas image. An example public repository supporting ephemeral images is ttl.sh, which is used in the commands below.
Building and Deploying the API
The complete list of commands needed to deploy the Leonidas API within a cluster are provided below:
0. Modify config.yml
to specify
- image_url
: the image URL i.e. the registry to temporary push the Leonidas container image so that the cluster can pull it from. We recommend the use of ephemeral images, therefore the current default value uses the ttl.sh registry with a few minutes image lifespan
- namespace
: the namespace which Leonidas resources should be deployed in. If not specified, Leonidas will be deployed into the default
namespace.
cd generator/
- Navigate to the generator directorypoetry install
- Install generator dependenciespoetry run ./generator.py generate-kube-api
- To generate the Python API code from the YAML definitionspoetry run ./generator.py build-image
- Build the Leonidas container image and push it to the remote registry. This might take a while.poetry run ./generator.py kube-resources > leonidas-manifests.yml
- Create the manifest of Kubernetes resources Leonidas needs, including the RBAC policy- by default, this command assumes cluster-wide operation and generates a cluster role. To specify explicitly whether Leonidas should be granted namespaced or cluster-wide permissions, set the
--role/--clusterrole
flag
- by default, this command assumes cluster-wide operation and generates a cluster role. To specify explicitly whether Leonidas should be granted namespaced or cluster-wide permissions, set the
kubectl -f leonidas-manifests.yml apply
- Create the Leonidas resources in the cluster. This might take a minute.kubectl port-forward deployment/leonidas-deployment 5000:5000
- Expose the Flask web service on http://localhost:5000 so that it can be accessed by clients such asleo
, Jupyter notebooks, or justcurl
. Note that if you chose to deploy Leonidas into a namespace other than the default, you will need to also provide the-n <your-namespace>
flag here
Removing Leonidas from a cluster
To clean up all Leonidas-related resources after use, simply run
kubectl -f leonidas-manifests.yml delete
Generating an RBAC Policy for the API
The generator utility allows generation of only the RBAC policy needed by Leonidas, without the other Kubernetes resources. This can be done using the rbac-policy
command.
Leonidas can be configured to run with cluster-wide permissions, or limited within a specific namespace. In practice, this means that the service account the application is running as can be assigned either a ClusterRole
, or a namespace-scoped Role
. In the latter scenario, cluster-wide permissions specified by test cases are ignored. See Writing Definitions on how this is specified. Depending on the mode of operation desired, the RBAC policy is generated as follows:
Running the Leonidas API Locally
It is possible to build and run the Leonidas Python API locally for development purposes. To do this:
cd generator
poetry install
poetry run ./generator.py generate-aws-api
and/orgenerate-kube-api
cd ../output/leonidas
poetry install
poetry run python leonidas.py
This will spawn the API listening at http://127.0.0.1:5000. By default, this uses whichever AWS credentials are configured as the default profile in ~/.aws/config
, and whichever Kubernetes credentials found in the default Kubeconfig. These can be overridden by supplying a role ARN to assume, access keys, JWT tokens or TLS client certificates to use for requests to the API.