Disclaimer: All changes that you might do are your own responsibility! Please backup your configuration files before changing them. I am not liable for any damages you might create following this blog post!
I do not describe the installation of CSE in detail. For a detailed describtion how to install CSE on RedHat Enterprise Linux or similar Linux systems, see: http://www.virtualizationteam.com/cloud/vmware-container-service-extension-2-6-1-installation-step-by-step.html.
With CSE2.6 an encryption of configuration files was introduced to protect confidential information like RabbitMQ, vCenter and VMware Cloud director password.
If you want to execute the Container Service extension as a Service you need to ensure the highest level of security possible, particularly in production, so let´s start at the beginning
The CSE configuration file
You should not leave any configuration information not encrypted, otherwise your server maybe more openly accessibly .
See below an example of a config.yaml.
amqp: exchange: cse-ext host: amqp.vmware.com password: guest port: 5672 prefix: vcd routing_key: cse ssl: false ssl_accept_all: false username: guest vhost: / vcd: api_version: '33.0' host: vcd.vmware.com log: true password: MySecretPassword port: 443 username: administrator verify: true vcs: - name: vc1 password: MySecretPassword username: cse_user@vsphere.local verify: true - name: vc2 password: MySecretPassword username: cse_user@vsphere.local verify: true service: enforce_authorization: false listeners: 10 log_wire: false telemetry: enable: true broker: catalog: cse default_template_name: my_template default_template_revision: 0 ip_allocation_mode: pool network: mynetwork org: myorg remote_template_cookbook_url: https://raw.githubusercontent.com/vmware/container-service-extension-templates/master/template.yaml storage_profile: '*' vdc: myorgvdc
By default CSE expects an encrypted config.yaml unless you use –skip-config-decryption.
To encrypt a config file use:
cse encrypt config.yaml --output encrypted-config.yaml
During the encryption of the file you are asked to define a password. This password is needed whenever you are using the configuration file.
You have to keep in mind that CSE does not have an internal possibility to store information like connections, credentials for needed connections or even for a state.
This means that CSE is completely stateless, with all advantages and disadvantages. One of the advantages is that you can redeploy CSE on any server as long as CSE is installed and you have the configuration file. One of the disadvantages is that you need to provide the configuration file and the password during startup of the service. This means you have to find a way to provide the password during the boot time.
To start CSE you will be prompted during the startup of the service to provide the password for the encrypted configuration file:
In a real world installation of CSE you do not want to start CSE manually, whenever your server reboots or during startup of a server. Therefore you need to have a systemd unit file to automatically start CSE. If you followed my post carefully, you might have an idea what the challenge might be: You have to provide a password during the boot time of the server.
You have to provide the password during boot time of the server in an environment variable $CSE_CONFIG_PASSWORD
.
There are two ways to declare this variable:
- in the init script
- in an environment script referenced in the startup script
- directly defined in the systemd unit file
Excursion: Systemd unit file
To understand how to define the variable it is useful to understand the structure of a systemd unit file. For more detail see: https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files
The init script contains of several sections. I will just explain section relevant for CSE that are the absolute basis:
- Unit
- Service
The Unit section looks like follows:
[Unit] Description=Container Service Extension for VMware vCloud Director Wants=network-online.target After=network-online.target
In the Unit section you describe the service itself as well as dependencies that need to be fulfilled to start your service successfully.
Wants means that the network service is a soft requirement meaning that the network service should be started but the init script will be executed even if the service was not started successfully.
After means that the service will be started after the network service was started.
The Service section looks like follows:
[Service] [Environment=CSE_CONFIG_PASSWORD='mysecretpassword'] optional ExecStart=/home/stefan/cse.sh User=stefan WorkingDirectory=/home/stefan Type=simple Restart=always [EnvironmentFile=/path/to/file] optional
In the section service you define the startup of the service like which executable should be started, which user to use for the startup of the service and which WorkingDirectory.
In our example of CSE,you will execute a shell script to start CSE.
ExecStart defines the executable which to use and how to call the executable.
User defines the user under which the service will be started.
WorkingDirectory defines which directory to use to store temporary information like log files.
EnviromentFile defines a file, in which you can set the environment that is used when the service is started.
Environment defines variables that are available during execution of the script. In our usecase you need either Environment, EnvironmentFile or none of them.
Define the variable in the init script
You can define CSE_CONFIG_PASSWORD
directly in the shell script that is called to start CSE. You have to add export CSE_CONFIG_PASSWORD=’mysecretpassword’ to the shell script like:
export CSE_CONFIG_PASSWORD='mysecretpassword' /home/stefan/.local/bin/cse run -c /home/stefan/encrypted-config.yaml
To ensure that that only and only the service user has read/write and execute permission ont the file because you have to store the password in clear text!
The environment variable is just valid for the time of execution and cannot be read by other users than the service user and root if somebody has unauthorized root access, you have another problem.
Define CSE_CONFIG_PASSWORD in the environment script
To define the config in the init script, you need to add EnvironmentFile=/path/to/file
to the cse.service systemd unit file.
A systemd unit file could look like follows:
[Unit] Description=Container Service Extension for VMware vCloud Director Wants=network-online.target After=network-online.target [Service] ExecStart=/home/stefan/cse.sh User=stefan WorkingDirectory=/home/stefan EnvironmentFile=/path/to/file Type=simple Restart=always [Install] WantedBy=default.target
Please be aware if the EnvironemntFile is not available during execution of the script, your script will fail and CSe will not start.
The environment file is quite easy:
CSE_CONFIG_PASSWORD='MySecretPassword'
You have to ensure that that only and only the service user has read/write and execute permission on the file because you have to store the password in clear text!
Definition in systemd unit file
To define the environment variable in the systemd unit file you just have to add Environment=CSE_CONFIG_PASSWORD='Mysecretpassword'
to the systemd unit file that defines the CSE startup.
You can find several examples of the unit file above.
You have to ensure that that only and only the service user has read/write and execute permission on the file because you have to store the password in clear text!
Sources
During the creation of this Blog entry I used several sources, that might be interested for further reading:
Systemd unifiles: https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files
systemd environments: https://coreos.com/os/docs/latest/using-environment-variables-in-systemd-units.html
CSE documentation: https://vmware.github.io/container-service-extension/INSTALLATION.html
And many discussion with colleagues like Eiad Al-Aqqad (see http://www.virtualizationteam.com/about)