CONDUIT Installation
This installation document will guide you through installing conduit and it's dependent components onto a machine without the use of docker containers
Build Conduit
Dependencies
- git
- go
Build Instructions
- Clone the repository
- Build the binaries
- Add Conduit to
/usr/local/bin
git clone https://github.com/lanl/conduit
cd conduit
# build server
go build -o conduit-server ./cmd/server
# build cli
go build -o conduit ./cmd/cli
# build fta
go build -o conduit-fta ./cmd/fta
# build runner
go build -o conduit-runner ./cmd/runner
# add symlink to /usr/local/bin
ln -s $(pwd)/conduit /usr/local/bin/conduit
Optional Version Information
A release version can optionally be embedded into each binary using the Go linker flag -ldflags. For example:
go build \
-ldflags="-X github.com/lanl/conduit/internal/version.Version=v2.0.4" \
-o conduit-server ./cmd/server
Replace v2.0.4 with the desired version and apply the same flag when building the other Conduit binaries.
If the flag is omitted, Conduit will still attempt to report the Git commit hash when available. When both are available, the version output includes the release version and commit hash.
Cert Generation
-
Create CONDUIT directory
/etc/conduit -
Populate CONDUIT config
/etc/conduit/config.yaml
auth:
external-ca-cert: /etc/conduit/keys/conduit-external-ca.pem
external-ca-key: /etc/conduit/keys/conduit-external-key.pem
internal-ca-cert: /etc/conduit/keys/conduit-internal-ca.pem
internal-ca-key: /etc/conduit/keys/conduit-internal-key.pem
keytab: /etc/krb5.keytab
requested-cert-lifetime: 24h
errant-lock: 336h
etcd:
- hostname: db-node1.example.com
ip: 192.168.0.18
port: 2379
- hostname: db-node2.example.com
ip: 192.168.0.19
port: 2379
- hostname: db-node3.example.com
ip: 192.168.0.20
port: 2379
ldap:
base-dn: []
host: ""
krb5-attributes: []
port: 389
uid-number-attributes:
- uidNumber
uname-attributes:
- uid
node-allocations:
setup:
memory: 10MB
nodes: 1
teardown:
memory: 10MB
nodes: 1
transfer:
memory: 500MB
nodes: 2
validation:
memory: 10MB
nodes: 1
nodes:
fta1:
address: fta1.example.com
port: 23457
min-memory: 1GB
max-jobs: 4
fta2:
# example of ip address instead of hostname
address: 192.168.20.7
port: 23457
min-memory: 1GB
max-jobs: 4
rqlite:
- hostname: db-node1.example.com
ip: 192.168.0.18
port: 4001
- hostname: db-node2.example.com
ip: 192.168.0.19
port: 4001
- hostname: db-node3.example.com
ip: 192.168.0.20
port: 4001
server:
hostname:
- conduit-server.example.com
ip:
- 192.168.0.254
- 204.121.70.130
port: 23456
ws-port: 8080
concurrency:
schedulers: 1
watchdogs: 1
transfer-workers: 1
test: false
transfer:
expiry-advance: 60s
max-source-bytes: 131072
- Generate certs:
CONDUIT_PATH=/etc/conduit
mkdir -p $CONDUIT_PATH/keys
# generate internal CA
conduit-server internal-ca -d
conduit-server external-ca -d
# generate server certs
for i in {1..3}; do
ip=$((i+17))
fta=$(printf %02d $(($i+8)))
conduit-server internal-server-cert \
-d \
--separate-cert-key \
--cert-name etcd_${i}_server_cert.pem \
--key-name etcd_${i}_server_key.pem \
--output /etc/conduit/keys/ \
--server-ip 192.168.0.${ip} \
--server-commonname etcd-${i} \
--server-hostname fta${fta}.example.com
conduit-server internal-server-cert \
-d \
--separate-cert-key \
--cert-name rqlite_${i}_server_cert.pem \
--key-name rqlite_${i}_server_key.pem \
--output /etc/conduit/keys/ \
--server-ip 192.168.0.${ip} \
--server-commonname rqlite-${i} \
--server-hostname fta${fta}.example.com
done
# generate cert for the slurm plugin to use for authentication
conduit-server external-client-cert \
-d \
--separate-cert-key \
--cert-name conduit-slurm-cert.pem \
--key-name conduit-slurm-key.pem \
--output /etc/conduit/keys/ \
--client-commonname conduit-service \ // this CN is unique, do not change
--expiration 365
# generate cert for admins to use for authentication
conduit-server external-client-cert \
-d \
--separate-cert-key \
--cert-name conduit-admin-cert.pem \
--key-name conduit-admin-key.pem \
--output /etc/conduit/keys/ \
--client-commonname conduit-admin \ // this CN is unique, do not change
--expiration 365
# generate cert to communicate with etcd for debugging
conduit-server internal-client-cert \
-d \
--separate-cert-key \
--cert-name etcd-client-cert.pem \
--key-name etcd-client-key.pem \
--output /etc/conduit/keys/ \
--expiration 365 \
--client-commonname root
ETCD Setup
-
Create the
etcduser -
Move binary to /usr/bin/etcd
-
Populate environment file at
/var/lib/etcd/environmentwith correct values:
ETCD_DATA_DIR=/var/lib/etcd/data
# unique name of this etcd node
ETCD_NAME=etcd-01
# ip for conduit to reach etcd
ETCD_LISTEN_CLIENT_URLS=https://192.168.0.18:2379
ETCD_ADVERTISE_CLIENT_URLS=https://192.168.0.18:2379
# ip for other etcd nodes to communicate with this node
ETCD_LISTEN_PEER_URLS=https://192.168.0.18:2380
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.0.18:2380
# addresses and names for all other etcd nodes
ETCD_INITIAL_CLUSTER=etcd-01=https://192.168.0.18:2380,etcd-02=https://192.168.0.19:2380,etcd-03=https://192.168.0.20:2380
# random token used during bootstrap. Should be the same across nodes
ETCD_INITIAL_CLUSTER_TOKEN=token-01
ETCD_INITIAL_CLUSTER_STATE=new
ETCD_LOG_LEVEL=debug
ETCD_LOGGER=zap
ETCD_LOG_OUTPUTS=default
# server cert and key used for communicating with conduit
ETCD_CERT_FILE=/var/lib/etcd/etcd-server-cert.pem
ETCD_KEY_FILE=/var/lib/etcd/etcd-server-key.pem
# the conduit internal ca cert
ETCD_TRUSTED_CA_FILE=/etc/conduit/keys/conduit-internal-ca.pem
# enable mTLS for conduit communication
ETCD_CLIENT_CERT_AUTH=1
# cert used for communicating with other etcd nodes
ETCD_PEER_CERT_FILE=/var/lib/etcd/etcd-server-cert.pem
ETCD_PEER_KEY_FILE=/var/lib/etcd/etcd-server-key.pem
ETCD_PEER_TRUSTED_CA_FILE=/etc/conduit/keys/conduit-internal-ca.pem
# enable mTLS for communication between etcd nodes
ETCD_PEER_CLIENT_CERT_AUTH=1
-
Install service file at
/usr/lib/systemd/system/etcd.service -
Start ETCD
systemctl enable etcd
systemctl start etcd
rqlite Setup
-
Create the
rqliteuser -
Move binary to /usr/bin/rqlite
-
Populate environment file at
/var/lib/rqlite/environmentwith correct values:
# unique id for this rqlite node
RQLITE_NODE_ID=1
# ip for conduit to reach rqlite (HTTP API)
RQLITE_HTTP_ADDR=192.168.0.18:4001
RQLITE_HTTP_ADV_ADDR=192.168.0.18:4001
# ip for other rqlite nodes to communicate with this node (Raft)
RQLITE_RAFT_ADDR=192.168.0.18:4002
RQLITE_RAFT_ADV_ADDR=192.168.0.18:4002
# Raft address that nodes should use to join cluster (note: uses Raft port 4002, not HTTP port)
RQLITE_JOIN=192.168.0.18:4002
# server cert and key used for communicating with conduit
RQLITE_CA_PATH=/etc/conduit/keys/conduit-internal-ca.pem
RQLITE_CERT_PATH=/var/lib/rqlite/rqlite-server-cert.pem
RQLITE_KEY_PATH=/var/lib/rqlite/rqlite-server-key.pem
# cert used for communicating with other rqlite nodes
RQLITE_PEER_CA_PATH=/etc/conduit/keys/conduit-internal-ca.pem
RQLITE_PEER_CERT_PATH=/var/lib/rqlite/rqlite-server-cert.pem
RQLITE_PEER_KEY_PATH=/var/lib/rqlite/rqlite-server-key.pem
-
Install service file in /usr/lib/systemd/system/rqlite.service
-
Start rqlite
systemctl enable rqlite
systemctl start rqlite
Conduit Server Setup
-
Copy
conduit-serverbinary to /usr/local/bin -
Install service file in /usr/lib/systemd/system/conduit-server.service
-
Start conduit-server
systemctl enable conduit-server
systemctl start conduit-server
Runner Setup
-
Copy over
conduit-runnerbinary to each fta node at /usr/local/bin -
Add
/etc/conduit/conduit-runner-config.yamlto all FTAs:
auth:
internal-ca-cert: /etc/conduit/keys/conduit-internal-ca.pem
internal-ca-key: /etc/conduit/keys/conduit-internal-key.pem
etcd:
- hostname: db-node1.example.com
ip: 192.168.0.18
port: 2379
- hostname: db-node2.example.com
ip: 192.168.0.19
port: 2379
- hostname: db-node3.example.com
ip: 192.168.0.20
port: 2379
fta:
path: /opt/storage/conduit/src/conduit-fta/conduit-fta
# options need to be single string with no spaces. Use '=' with flags
options:
- "--config=/opt/storage/conduit/configs/conduit-fta-config.yaml"
- "-d" # debug mode
environment:
path: "/bin:/usr/bin/:/usr/local/bin/:/usr/local/sbin:/usr/sbin"
ld-Library-Path: "/lib/:/lib64/:/usr/local/lib"
server:
hostname:
- fta1.example.com
ip:
- 192.168.20.6
port: 23457
-
Install service file in /usr/lib/systemd/system/conduit-runner.service
-
Start conduit-runner
systemctl enable conduit-runner
systemctl start conduit-runner
FTA Setup
-
Copy over
conduit-ftabinary to each fta node. This needs to be in the location specified in the conduit runner config created earlier -
Add
/etc/conduit/conduit-fta-config.yamlto all FTAs:
auth:
internal-ca-cert: /etc/conduit/keys/conduit-internal-ca.pem
conduit:
expiry-advance: 5m
expiry-interval: 30s
etcd:
- ip: 192.168.0.18
port: 2379
- ip: 192.168.0.19
port: 2379
- ip: 192.168.0.20
port: 2379
fta:
verify-retry-count: 20
verify-sleep-duration: 5s
plugins:
pftool:
pfcp-path: /opt/software/campaign/install/bin/pfcp
rsync:
rsync-path: rsync
filesystems:
nfs-scratch:
user-path: ^/nfs-scratch/scratch([0-9]+)/(.*)
fta-root-fs-path: /nfs-scratch/
fta-path: /nfs-scratch/scratch$1/$2
plugin-stages:
validation: posix
setup-src: posix
setup-dst: posix
transfer-src:
- pftool
transfer-dst:
- pftool
teardown-src: posix
teardown-dst: posix
custom-plugin-config:
posix-src-trash: ""
pftool-no-progress-timeout-hours: 1
marfs:
user-path: ^(/marfs)?/(campaign)/([\w\-. ]+)(/.*)?
fta-root-fs-path: /marfs/$2/
fta-path: /marfs/$2/$3$4
plugin-stages:
validation: posix
setup-src: posix
setup-dst: posix
transfer-src:
- pftool
transfer-dst:
- pftool
teardown-src: posix
teardown-dst: posix
custom-plugin-config:
posix-src-trash: ""
pftool-no-progress-timeout-hours: 1
marchive:
user-path: ^(/marfs)?/(archive)/([\w\-. ]+)(/.*)?
fta-root-fs-path: /marfs/$2/
fta-path: /marfs/$2/$3$4
plugin-stages:
validation: posix
setup-src: marchive
setup-dst: posix
transfer-src:
- pftool
transfer-dst:
- pftool
teardown-src: marchive
teardown-dst: posix
custom-plugin-config:
posix-src-trash: ""
pftool-no-progress-timeout-hours: 1
Kerberos Setup
Kerberos Instructions:
-
Get keytab from security
-
Move keytab to
/etc/krb5.keytab -
Create config file
/etc/krb5.conf:
# Configuration snippets may be placed in this directory as well
includedir /etc/krb5.conf.d/
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
dns_lookup_realm = false
ticket_lifetime = 10h
renew_lifetime = 7d
forwardable = true
rdns = false
pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt
default_realm = HPC.EXAMPLE.COM
default_ccache_name = FILE:/tmp/krb5cc_%{uid}
[realms]
HPC.EXAMPLE.COM = {
kdc = hpc-auth1.example.com:88
kdc = hpc-auth2.example.com:88
admin_server = hpc-auth1.example.com:749
default_domain = example.com
pkinit_identities = PKCS11:opensc-pkcs11.so
pkinit_anchors = FILE:/etc/krb5.anchors.hpc.pem
pkinit_pool = FILE:/etc/krb5.pool.hpc.pem
}
[kdc]
profile = /var/kerberos/krb5kdc/kdc.conf
[appdefaults]
pam = {
debug = true
}
- Create reticket script in
/usr/sbin/reticket:
#!/bin/bash
# Script to test if there is a Turquoise ticket, when running in the
# Turquoise RE. Nothing is done, if not in the RE. Make use of LOGNAME
# environment variable.
rc=0
# Need to figure out if we are in the RE
if [ -n "`grep default_realm /etc/krb5.conf | grep HPC.EXAMPLE.COM`" ]; then
TURQ_TICKET="$(klist | grep '^Default principal:' | grep '@HPC.EXAMPLE.COM')"
# If there is no Turquoise ticket, then need to create one ...
if [ -z "$TURQ_TICKET" ]; then
echo "Need to generate Turquoise Kerberos ticket..."
kinit -n @HPC.EXAMPLE.COM
kinit -T "$(klist | grep '^Ticket cache:' | sed 's/^Ticket cache: //')" ${LOGNAME}@HPC.EXAMPLE.COM
# echo "Return: $?"
rc=$?
fi
fi
exit $rc
-
Download
krb5.anchors.hpc.pemandkrb5.pool.hpc.pemfrom organization. Put them in/etc/ -
Install packages:
yum install krb5-pkinit krb5-workstation pam_krb5 krb5-libs
- Install organization specific certs:
yum install organization-krb-certs...rpm