During the last days, figured out a couple of things.
This is done through simple HTTP calls to different endpoints under http://host:15672/api/
. All the calls use HTTP Basic Authentication with username and password of a RabbitMQ user with appropriate permissions.
To create a user and vhost and grant the user access to this vhost only:
- Create user (without any tags)
- Create vhost
- Create permission linking user with vhost
This will be used in the post-signup Lambda function (implemented in Go with the net/http
package).
How to use the AWS SDK for Go (aws-sdk-go)
- Create a session with common configuration information (region, credentials, profile)
- Ceate a service client for the desired AWS service (there's a Go package for every supported AWS service)
- Make requests to the AWS service with the service client.
Every AWS service is in fact exposed as an HTTP API and the service client makes requests to this API. There is a documentation of the APIs of all services, for example here for AWS Secrets Manager. An overview with links to the documentation of all services can be found here.
The AWS Console (website) and AWS CLI also carry out their operations by making requests to these APIs. It is not recommended to use the HTTP of an AWS service directly (e.g. with curl
). Instead, always use either an AWS SDK, the AWS CLI, or the AWS Console as these implementations handle many low-level details.
Pretty straighforward once it is clear how the AWS SDK for Go works.
This will be needed to read the credentials of the RabbitMQ admin user from the post-signup Lambda function.
The Kubernetes Go client (client-go) doesn't provide any easy means for this. The best solution seems to be to use the github.com/ghodss/yaml package to read YAML into a client-go API object struct. This works pretty well:
import (
"io/ioutil"
"github.com/ghodss/yaml"
"k8s.io/api/apps/v1"
)
func main() {
bytes, err := ioutil.ReadFile("deployment.yml")
if err != nil {
panic(err.Error())
}
var spec v1.Deployment
err = yaml.Unmarshal(bytes, &spec)
if err != nil {
panic(err.Error())
}
}
This can also be used in the post-signup Lambda function so that we can define the backend deployment object in a file rather than as a struct in the Go code.
Btw, if the API objects are defined in JSON files, they can be read even easier with standar library means, see here.
- Create Kubernetes cluster
- Apply CloudFormation template plus some additional setup
- Deploy and set up RabbitMQ
- Deploy RabbitMQ deployment and service to cluster
- Replace default admin user (guest/guest) with a new one with a safe password
- Store credentials of new admin user in AWS Secrets Manager
- Store URL of RabbitMQ service somewhere (TODO: where?)
- Needs to be retrieved by frontend and post-signup Lambda function
- (Deploy frontend)
- In post-signup Lambda function:
- Retrieve RabbitMQ service URL
- Retrieve RabbitMQ admin credentials from AWS Secrets Manager
- Create a new user and vhost on RabbitMQ (granting user access to only this vhost)
- Create a backend deployment in the cluster and link with this vhost
- Store credentials for this RabbitMQ user (username, password, vhost) somewhere (TODO: where?)
- These need to be retrieved by the frontend when connecting to the backend (together with the RabbitMQ service URL)
Currently, secrets like the Telegram API ID and Hash are saved as Kubernetes secrets in the cluster. Should they also be saved in AWS Secrets Manager so that all the secrets are together?
List of tings that have to be saved for each human user:
- Account username and password (saved in Amazon Cognito)
- RabbitMQ username, password, vhost
- Application data (it's probably better to save this persistently for the case of a pod crash)
- Telethon session file
- Telegram phone number
- Lists of peers, patterns, and notification emails