Skip to content

Commit

Permalink
Merge pull request #31 from epics-extensions/ca-gateway
Browse files Browse the repository at this point in the history
CA gateway
  • Loading branch information
minijackson authored Oct 27, 2023
2 parents e1c4ae7 + 43166cf commit a6c67fb
Show file tree
Hide file tree
Showing 11 changed files with 639 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/_quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ website:
- ./nixos/tutorials/archiver-appliance.md
- section: User Guides
contents:
- ./nixos/guides/ca-gateway.md
- ./nixos/guides/phoebus-alarm.md
- section: Explanations
- section: References
Expand Down
195 changes: 195 additions & 0 deletions doc/nixos/guides/ca-gateway.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
---
title: Channel Access gateway setup
---

The Channel Access (CA) gateway is a program
that acts as gateway,
which enables client from a network to access IOCs on another network.

Setting up a CA gateway also enables you
to add extra access security rules on top of IOCs.

For more details and documentation about the CA PV gateway,
you can examine the [gateway main page].

[gateway main page]: https://epics.anl.gov/extensions/gateway/

{{< include _pre-requisites.md >}}

# Enabling the gateway

To enable the gateway,
add this to your configuration:

``` nix
{
services.ca-gateway = {
enable = true;
openFirewall = true;
};
}
```

This configuration starts the CA gateway in a `ca-gateway.service` systemd service.
In this configuration,
the gateway listens on all interface with a broadcast IP address,
and forwards all Channel Access request.

The `openFirewall` option opens the
5064 TCP,
5064 UDP,
and 5065 UDP ports on all network interfaces.

# Firewall on specific interfaces

If you want to enable the firewall on specific interfaces,
you can remove the `openFirewall` option
and configure the firewall manually.

You can also use the `cip` setting
to specify where the gateway should listen
for the CA server part.

For example:

``` nix
{config, ...}: {
services.ca-gateway = {
enable = true;
# Server side listen address
# Let's say this IP address is on enp0s2
settings.sip = ["10.0.2.1"];
# Let's also say the enp0s1 interface is
# where communication with "real" IOCs happen (client side)
# openFirewall is left as false by default
};
networking.firewall = let
gwSettings = config.services.ca-gateway.settings;
in {
interfaces = {
# Open the firewall on the interface from the client side of the gateway,
# this will be the side of the gateway listening
# for replies to beacons and PV search requests
"enp0s1".allowedUDPPorts = [5065];
# Open the firewall on the interface from the server side of the gateway,
# this will be the side of the gateway listening for Channel Access requests
"enp0s2" = {
# Use the value of the `sport` setting
allowedTCPPorts = [gwSettings.sport];
allowedUDPPorts = [gwSettings.sport];
};
};
# Allow incoming UDP packets with *source* port 5064,
# from the client side of the gateway.
# This is needed to listen to CA broadcast responses
extraCommands = ''
ip46tables -A nixos-fw -p udp --sport 5064 -j nixos-fw-accept -i enp0s1
'';
};
}
```

# Filtering IOCs

By using the `cip` setting,
you can filter which IOCs get exposed by the gateway.
This is equivalent to setting the environment variable `EPICS_CA_ADDR_LIST`
and setting `EPICS_CA_AUTO_ADDR_LIST=NO`.

For example:

``` nix
{
services.ca-gateway = {
enable = true;
# These IOCs get exposed by the gateway
settings.cip = [
"10.0.1.42"
"10.0.1.69"
# you can specify the port, too,
# if your IOC listens on something other than 5064
"10.0.1.237:5067"
# domain names also work
"myioc"
];
};
}
```

# Filtering process variables

By using the `pvlist` setting,
you can filter which PVs get exposed by the gateway.

This option takes a file in the gateway `pvlist` format.
See the [`GATEWAY.pvlist`] example on the ca-gateway repository.
The list supports regular expressions (Perl style).

[`GATEWAY.pvlist`]: https://github.com/epics-extensions/ca-gateway/blob/master/example/GATEWAY.pvlist

## In the configuration

For example:

``` nix
{pkgs, ...}: {
services.ca-gateway = {
enable = true;
# These PVs get exposed by the gateway
# This list implements an "allowlist":
# DENY by default, some PVs explicitely ALLOW
settings.pvlist = pkgs.writeText "gateway.pvlist" ''
EVALUATION ORDER DENY, ALLOW
.* DENY
MY_PV1 ALLOW
MY_PV2 ALLOW
# Or:
MY_PV[0-9]+ ALLOW
'';
};
}
```

## In a separate file

For long lists,
it can be better
to put it in a separate file.
You can do this
by adding a `gateway.pvlist` in the same directory as your configuration:

``` {.perl filename="gateway.pvlist"}
EVALUATION ORDER DENY, ALLOW

.* DENY

MY_PV1 ALLOW
MY_PV2 ALLOW

# Or:

MY_PV[0-9]+ ALLOW
```

And in your configuration:

``` nix
{
services.ca-gateway = {
enable = true;
# Make sure that the value is *not* quoted
settings.pvlist = ./gateway.pvlist;
};
}
```
1 change: 1 addition & 0 deletions lib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ with lib; let
formats = import ./formats.nix args;
licenses = import ./licenses.nix args;
maintainers = import ./maintainers/maintainer-list.nix;
testing = import ./testing.nix;

evalEpnixModules = {
nixpkgsConfig,
Expand Down
33 changes: 33 additions & 0 deletions lib/testing.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
# Takes the content of an EPICS db file (db).
# Outputs a NixOS configuration that starts a soft ioc systemd service.
#
# Usage example:
#
# {
# imports = [
# (softIoc ''
# record(ai, "EXAMPLE_PV") { }
# '')
# ];
# virtualisation.vlans = [1];
# }
softIoc = db: {pkgs, ...}: let
dbfile = pkgs.writeText "softIoc.db" db;
in {
systemd.services.ioc = {
wantedBy = ["multi-user.target"];
wants = ["network-online.target"];
after = ["network-online.target"];

serviceConfig = {
ExecStart = "${pkgs.epnix.epics-base}/bin/softIoc -S -d ${dbfile}";
DynamicUser = true;
};
};
environment.systemPackages = [pkgs.epnix.epics-base];

networking.firewall.allowedTCPPorts = [5064 5065];
networking.firewall.allowedUDPPorts = [5064 5065];
};
}
1 change: 1 addition & 0 deletions nixos/module-list.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[
./modules/archiver-appliance.nix
./modules/ca-gateway.nix
./modules/phoebus/alarm-logger.nix
./modules/phoebus/alarm-server.nix
./modules/phoebus/local-kafka.nix
Expand Down
Loading

0 comments on commit a6c67fb

Please sign in to comment.