You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+105-4Lines changed: 105 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,6 +10,10 @@ Containers, networks, volumes and images are node specific resources, not cluste
10
10
11
11
The purpose of the agent aims to allows previously node specific resources to be cluster-aware, all while keeping the Docker API request format. As aforementioned, this means that you only need to execute one Docker API request to retrieve all these resources from every node inside the cluster. In all bringing a better Docker user experience when managing Swarm clusters.
12
12
13
+
## Security
14
+
15
+
Here at Portainer, we believe in [responsible disclosure](https://en.wikipedia.org/wiki/Responsible_disclosure) of security issues. If you have found a security issue, please report it to <security@portainer.io>.
16
+
13
17
## Technical details
14
18
15
19
The Portainer agent is basically a cluster of Docker API proxies. Deployed inside a Swarm cluster on each node, it allows the
@@ -22,6 +26,11 @@ At startup, the agent will communicate with the Docker node it is deployed on vi
22
26
This implementation is using *serf* to form a cluster over a network, each agent requires an address where it will advertise its
23
27
ability to be part of a cluster and a join address where it will be able to reach other agents.
24
28
29
+
The agent retrieves the IP address it can use to create
30
+
a cluster by inspecting the Docker networks associated to the agent container. If multiple networks are available, it will pickup the first network available and retrieve the IP address inside this network.
31
+
32
+
Note: Be careful when deploying the agent to not deploy it inside the Swarm ingress network (by not using `mode=host` when exposing ports). This could lead to the agent being unable to create a cluster correctly, if picking the IP address inside the ingress network.
33
+
25
34
### Proxy
26
35
27
36
The agent works as a proxy to the Docker API on which it is deployed as well as a proxy to the other agents inside the cluster.
@@ -72,6 +81,10 @@ The agent also exposes the following endpoints:
72
81
*`/browse/put` (*POST*): Upload a file under a specific path on the filesytem
73
82
*`/host/info` (*GET*): Get information about the underlying host system
74
83
*`/ping` (*GET*): Returns a 204. Public endpoint that do not require any form of authentication
84
+
*`/key` (*GET*): Returns the Edge key associated to the agent **only available when agent is started in Edge mode**
85
+
*`/key` (*POST*): Set the Edge key on this agent **only available when agent is started in Edge mode**
Note: The `/browse/*` endpoints can be used to manage a filesystem. By default, it allows manipulation of files in Docker volumes (available under `/var/run/docker/volumes` when bind-mounted in the agent container) but can also manipulate files anywhere on the filesystem. To enable global
77
90
filesystem manipulation support for these endpoints, the `CAP_HOST_MANAGEMENT` environment variable must be set to `1`.
@@ -80,7 +93,87 @@ filesystem manipulation support for these endpoints, the `CAP_HOST_MANAGEMENT` e
80
93
81
94
The agent API version is exposed via the `Portainer-Agent-API-Version` in each response of the agent.
82
95
83
-
## Security
96
+
## Using the agent in Edge mode
97
+
98
+
The following information is only relevant for an Agent that was started in Edge mode.
99
+
100
+
### Purpose
101
+
102
+
The Edge mode is mainly used in the case of your remote environment being not in the same network as your Portainer instance. When started in Edge mode, the agent will reach out to the Portainer instance
103
+
and will take care of creating a reverse tunnel allowing the Portainer instance to query it. It uses a token (Edge key) that contains the required information to connect to a specific Portainer instance.
104
+
105
+
### Startup
106
+
107
+
To start an agent in Edge mode, the `EDGE=1` environment variable must be set.
108
+
109
+
Upon startup, the agent will try to retrieve an existing Edge key in the following order:
110
+
111
+
* from the environment variables via the `EDGE_KEY` environment variable
112
+
* from the filesystem (see the Edge key section below for more information about key persistence on disk)
113
+
* from the cluster (if joining an existing Edge agent cluster)
114
+
115
+
If no Edge key was retrieved, the agent will start a HTTP server where it will expose a UI to associate an Edge key. After associating a key via the UI, the UI server will shutdown.
116
+
117
+
For security reasons, the Edge server UI will shutdown after 15 minutes if no key has been specified. The agent will require a restart in order
118
+
to access the Edge UI again.
119
+
120
+
### Edge key
121
+
122
+
The Edge key is used by the agent to connect to a specific Portainer instance. It is encoded using base64 and contains the following information:
123
+
124
+
* Portainer instance API URL
125
+
* Portainer instance tunnel server address
126
+
* Portainer instance tunnel server fingerprint
127
+
* Endpoint identifier
128
+
129
+
This information is represented in the following format before encoding (single string using the `|` character as a separator):
The Edge key associated to an agent will be persisted on disk after association under `/data/agent_edge_key`.
136
+
137
+
### Polling
138
+
139
+
After associating an Edge key to an agent, the agent will start polling the associated Portainer instance.
140
+
141
+
It will use the Portainer instance API URL and the endpoint identifier available in the Edge key to build the poll request URL: `http(s)://API_URL/api/endpoints/ENDPOINT_ID/status`
142
+
143
+
The response of the poll request contains the following information:
144
+
145
+
* Tunnel status
146
+
* Poll frequency
147
+
* Tunnel port
148
+
* Encrypted credentials
149
+
* Schedules
150
+
151
+
The tunnel status property can take one of the following values: `IDLE`, `REQUIRED`, `ACTIVE`. When this property is set to `REQUIRED`, the agent will
152
+
create a reverse tunnel to the Portainer instance using the port specified in the response as well as the credentials.
153
+
154
+
Each poll request sent to the Portainer instance contains the `X-PortainerAgent-EdgeID` header (with the value set to the Edge ID associated to the agent). This is used by the Portainer instance to associate an Edge ID to an endpoint so that an agent won't be able to poll information and join an Edge cluster by re-using an existing key without knowing the Edge ID.
155
+
156
+
To allow for pre-staged environments, this Edge ID is associated to an endpoint by Portainer after receiving the first poll request from an agent.
157
+
158
+
### Reverse tunnel
159
+
160
+
The reverse tunnel is established by the agent. The permissions associated to the credentials are set on the Portainer instance, the credentials are valid for a management session and can only be used
161
+
to create a reverse tunnel on a specific port (the one that is specified in the poll response).
162
+
163
+
The agent will monitor the usage of the tunnel. The tunnel will be closed in any of the following cases:
164
+
165
+
1. The status of the tunnel specified in the poll response is equal to `IDLE`
166
+
2. If no activity has been registered on the tunnel (no requests executed against the agent API) after a specific amount of time (can be configured via `EDGE_INACTIVITY_TIMEOUT`, default to 5 minutes)
167
+
168
+
### API server
169
+
170
+
When deployed in Edge mode, the agent API is not exposed over HTTPS anymore (see Using the agent non Edge section below) because we're using SSH to setup an encrypted tunnel. In order to avoid potential security issues with agent deployment exposing the API port on their host, the agent won't expose the API server under 0.0.0.0. Instead, it will expose the API server on the same IP address that is used to advertise the cluster (usually, the container IP in the overlay network).
171
+
172
+
This means that only a container deployed in the same overlay network as the agent will be able to query it.
173
+
174
+
## Using the agent (non Edge)
175
+
176
+
The following information is only relevant for an Agent that was not started in Edge mode.
84
177
85
178
### Encryption
86
179
@@ -132,17 +225,25 @@ This mode will allow multiple instances of Portainer to connect to a single agen
132
225
133
226
Note: Due to the fact that the agent will now decode and parse the public key associated to each request, this mode might be less performant than the default mode.
134
227
135
-
136
228
## Deployment options
137
229
138
230
The behavior of the agent can be tuned via a set of mandatory and optional options available as environment variables:
139
231
140
232
* AGENT_CLUSTER_ADDR (*mandatory*): address (in the IP:PORT format) of an existing agent to join the agent cluster. When deploying the agent as a Docker Swarm service,
141
233
we can leverage the internal Docker DNS to automatically join existing agents or form a cluster by using `tasks.<AGENT_SERVICE_NAME>:<AGENT_PORT>` as the address.
142
-
* AGENT_PORT (*optional*): port on which the agent web server will listen (default to `9001`).
143
-
* CAP_HOST_MANAGEMENT (*optional*): enable advanced filesystem management features. Disabled by default, set to `1` to enable it.
234
+
* AGENT_HOST (*optional*): address on which the agent API will be exposed (default to `0.0.0.0`)
235
+
* AGENT_PORT (*optional*): port on which the agent API will be exposed (default to `9001`)
236
+
* CAP_HOST_MANAGEMENT (*optional*): enable advanced filesystem management features. Disabled by default, set to `1` to enable it
144
237
* AGENT_SECRET (*optional*): shared secret used in the signature verification process
145
238
* LOG_LEVEL (*optional*): defines the log output verbosity (default to `INFO`)
239
+
* EDGE (*optional*): enable Edge mode. Disabled by default, set to `1` to enable it
240
+
* EDGE_KEY (*optional*): specify an Edge key to use at startup
241
+
* EDGE_ID (*mandatory when EDGE=1*): a unique identifier associated to this agent cluster
242
+
* EDGE_SERVER_HOST (*optional*): address on which the Edge UI will be exposed (default to `0.0.0.0`)
243
+
* EDGE_SERVER_PORT (*optional*): port on which the Edge UI will be exposed (default to `80`).
244
+
* EDGE_INACTIVITY_TIMEOUT (*optional*): timeout used by the agent to close the reverse tunnel after inactivity (default to `5m`)
245
+
* EDGE_INSECURE_POLL (*optional*): enable this option if you need the agent to poll a HTTPS Portainer instance with self-signed certificates. Disabled by default, set to `1` to enable it
246
+
146
247
147
248
For more information about deployment scenarios, see: https://portainer.readthedocs.io/en/stable/agent.html
Copy file name to clipboardExpand all lines: cmd/agent/main.go
+20-23Lines changed: 20 additions & 23 deletions
Original file line number
Diff line number
Diff line change
@@ -41,46 +41,57 @@ func main() {
41
41
log.Println("[INFO] [main] [message: Agent running on a Swarm cluster node. Running in cluster mode]")
42
42
}
43
43
44
-
ifoptions.ClusterAddress==""&&clusterMode {
45
-
log.Fatalf("[ERROR] [main,configuration] [message: AGENT_CLUSTER_ADDR environment variable is required when deploying the agent inside a Swarm cluster]")
log.Printf("[WARN] [docker] [network_count: %d] [message: Agent container running in more than a single Docker network. This might cause communication issues]", len(containerInspect.NetworkSettings.Networks))
0 commit comments