Security
Security, in the context of a Cloudify Manager, means securing communication with the Cloudify Manager and controlling who
has permissions to use it to execute various operations.
Secured communication is achieved using SSL, which allows clients to validate the authenticity of the Cloudify Manager,
and to ensure that the data sent to and from it is encrypted.
Controlling access to Cloudify Manager, and permissions to perform actions, is implemented via Flask-Security, to support user authentication and authorization.
Cloudify Manager is secured by default. It cannot be bootstrapped in a non-secured way.
Details about Cloudify’s SSL and Access Control implementation and configuration are provided below.
Cloudify security for client access focuses on the REST service, which this is the first and only access point of clients to
Cloudify Manager. All requests to Cloudify Manager are authenticated and authorized before reaching their endpoint.
For example, when a Cloudify Management Console user attempts to upload a new blueprint, a request is sent to the REST service’s
/blueprints endpoint through port 80 / 443. The request only reaches the endpoint if the user is logged in and is authorized to upload
blueprints. Similarly, a user who executes the CLI command cfy deployments list
triggers a request to execute GET
on
/deployments that is only be successful if it includes valid credentials that identify an authorized
user.
Requests generated by other HTTP clients (e.g. curl) must also include valid credentials. Required credentials are a user name and password, or a Cloudify-generated token, and a tenant name. If credentials are missing, invalid, or represent an unauthorized user, the request fails with a “401: Unauthorized User”
error.
The /version endpoint is not a secured resource, and is therefore open to all users.
Authorization
A combination of roles, permissions and multi-tenancy provides the framework for authorization and resource isolation.
Roles and Permissions
Cloudify includes built-in user roles with which users are associated:
Administrator
User
Each role has different permissions, ensuring a role-based access control operation. For example, users with the user
role cannot perform Cloudify administration operations such as snapshot management. A user can be suspended using the deactivate
command. A deactivated user cannot perform operations.
Isolation
Cloudify supports the concept of users, user groups, and tenants. These elements can be either defined locally in Cloudify, or taken from an external user management system (LDAP integration is native). In the latter case, passwords are not stored in Cloudify, authentication is performed via LDAP and a token is generated and used for the user session.
A user can be associated with one or more groups, and one or more tenants.
A group can be associated with one or more tenant.
A user who is authenticated to Cloudify may only access resources that belong to the tenants to which that user has been assigned. Resource isolation is implemented for blueprints, artifacts, deployments, nodes, logs, events, and plugins.
An additional layer of permission control is implemented on resources, allowing private resource configuration. A resource that is created as private is only visible to the user who created that resource, and not to other users within the tenant. The exception is a user with an admin
role, who has full access to all system resources.
All REST APIs, except admin APIs and the version API, require a tenant, and operations are associated with the specified tenant. In the case of Read operations, only information about the specified tenant is returned. In the case of Write operations, the resource is added to the specified tenant.
Admin APIs are provided for the following resources (and are available only to admin
users):
- Tenant management (CRUD)
- User management (CRUD)
- User group management (CRUD)
- Snapshot management (CRD)
- Cluster management (configuration of manager HA)
- Maintenance mode activation/de-activation
- Upgrade/rollback commands
RabbitMQ isolation is achieved through the use of virtual hosts and the association between hosts and users, which enables authorization at the queue/exchange level and results in isolation of queues between tenants. In this configuration it is impossible for a host VM from tenant A to access/request operations on host VMs that belong to tenant B.
Communication
Scope
Communication from the external environment to Cloudify Manager and its SSL/TLS configuration is the user’s responsibility (CA/host verification, etc.), where the endpoints include the UI and REST API. Communication between Cloudify agents and Cloudify Manager (and within Cloudify Manager) is the responsibility of Cloudify, and is determined by Cloudify. Cloudify generates the necessary certificates for internal communication. Credentials do not appear in log files (cloud/RabbitMQ/Cloudify).
Communication channels
- Internal services access the REST API/file server over HTTPS on port 53333 through the manager’s private IP with a Cloudify generated authentication token.
- External access to REST API/file server (e.g. CLI, UI) is done by default over HTTP through the manager’s public IP, but can be configured to use HTTPS with a customer-signed certificate. Authentication is done via a Cloudify generated authentication token or with user and password.
- Agents access the manager over two secure channels: AMQP (5671) and HTTPS (53333). By default agents access the manager over its private IP, but can be configured to use other additional IPs.
SSL for internal communication
All internal communications between internal services/agents and the REST API/RabbitMQ are done over SSL.
During the bootstrap, the manager creates (or accepts as input) an internal CA certificate and key. Cloudify then creates an SSL keypair with a matching certificate that contains the private IP and all the management network IPs as its CN value. The keypair is used by both RabbitMQ and REST API/file server for internal access.
As part of the agent’s installation script, Cloudify’s internal CA certificate is propagated to the agent’s host in order to validate the manager’s certificate. There are no agent-host certificates.
Customizing SSL for internal communication
You can override the internal Manager certificate, and the CA certificate
in the Cloudify Manager configuration. To provide a custom internal CA certificate
for the agents to use, add the ca_certificate
and optionally ca_key
inputs must be set
in the /opt/cloudify/config.yaml file during (installation or update
of the Cloudify Manager.
To provide a custom internal certificate, use the internal_certificate
and
internal_key
inputs. If none are provided, Cloudify will generate the CA and
the internal certificate automatically.
If provided, the internal certificate must be generated with the appropriate subjectAltName extension to allow connections over every used Manager IP or hostname. The internal certificate must be signed by the CA certificate.
If the ca_certificate
and ca_key
inputs are provided, the internal certificate
will be generated and signed using the provided CA. If the ca_certificate
is
provided, but ca_key
is NOT provided, then Cloudify cannot generate the internal
certificate and the internal_certificate
and internal_key
inputs are required.
In order to use a Cloudify Manager cluster, the CA key must be present - either
generated automatically by Cloudify, or passed in the ca_key
input.
SSL mode for external communication
Cloudify manager, by default, doesn’t use SSL for external communication. You can set the manager to use ssl for the external communication during bootstrap or after bootstrap.
During bootstrap, you can edit the manager blueprint input.
In the Security Settings section, set ssl_enabled
parameter to true, in order to set the manager ssl mode.
You can set the rest_certificate and rest_key parameters, to use your own certificate. If missing, the manager will auto generate the certificate.
After bootstrap, you can use cfy ssl
command to enable or disable the ssl mode.
You can also change the manager certificate by replacing the files under /etc/cloudify/ssl/
.
The relevant files are: cloudify_external_cert.pem and cloudify_external_key.pem.
When bootstrapping with ssl mode, during the bootstrap the certificate will be copied to the local cli-profile. When using CA signed certificate, you’ll need to update it in the cli-profile (to contain the CA certificate and not the manager certificate) or to remove it (depends on the organization configuration)
In order to update the certificate in the cli-profile, you’ll need to run the following command:
cfy profile set --rest-certificate CA_CERT_PATH
In case you renew the certificate, just update it in the manager, under /etc/cloudify/ssl.
Additional Security Information
- All services required by Cloudify run under the Cloudify (and not root) user in the manager VM. The only exception is the parent process of Nginx, which runs as root in order to enable use of port 80. It is not recommended to change this behavior.
- A secrets store is implemented inside the Cloudify PostgreSQL database, which provides a tenant-wide variable store.
- Through usage of the secrets store, a user can ensure all secrets (such as credentials to IaaS environments, passwords, and so on) are stored securely and separately from blueprints, and adhere to isolation requirements between different tenants.
- Users need not know the actual values of a secret parameter (such as a password), since they can just point to the secrets store.
- Secrets can be added to the store using a
SET
function, and retrieved viaGET
. - Plugins can access the secrets store, to leverage the secrets when communicating with IaaS environments.
- Cloudify Manager instances must be secured via SSL to ensure secrets are not passed on an unencrypted communication channel.
- Use of PostgreSQL ensures that secrets are replicated across all Cloudify Manager instances within a cluster, as part of HA.
For more information about the secrets store, click here.