Skip to content

Instantly share code, notes, and snippets.

@bpluly
Last active October 31, 2023 16:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bpluly/7777c72211bf0002a1ade54a88e31bc3 to your computer and use it in GitHub Desktop.
Save bpluly/7777c72211bf0002a1ade54a88e31bc3 to your computer and use it in GitHub Desktop.
Using rsync from Fabric2/Patchwork/Paramiko on AWS EIC connections to update certificates on HAProxy

Further adventures in EIC land. I use Fabric2 for all the distribution of code and as much Opswork as I can. That includes updating certs. The certs are all managed from my local machine and then distributed. I use rsync to move the certificate trees (all LetsEncrypt). Before using EIC this was simple the same ssh config could be used but had to be repeated for the Patchwork rsync as it makes its own connection even though there's an existing connection to the host. The ssh_opts for EIC mean you have to inject the InstanceId for each host, the Paramiko Connection object might have it but I failed to find it spelunking; it relies on the ssh_opts parameter to fill the rsync options.

Using the EC2 API DescribeInstances gets the InstanceId along with everything else about the instance and using the Private DNS for the host filters the API response. To get the Private DNS on my ssh config I use the Connection objects which has the updated host string, converting Hostname to the Host which is either an IP address or the DNS name. I use the DNS name in the ssh config.

####A scrap of code.

  ec2 = session.client('ec2')   
  certPath = configEnv['certPath']
  localPath = configEnv['localPath']
  path = configEnv['path']
  for host in configEnv['hosts']:
    with Connection(host) as conn:
      conn = Connection(host)
      hostConnection = []
      hostConnection.insert(1, conn.host)
      response = ec2.describe_instances(Filters=[{'Name':'private-dns-name', 'Values': hostConnection}])
      if response != None:
        instanceID = response['Reservations'][0]['Instances'][0]['InstanceId']
      else:
        print("InstanceId not returned for host.")
        return
      ssh_opts = '-o "ProxyCommand  aws ec2-instance-connect open-tunnel --instance-id "'+instanceID
      transfers.rsync(conn, localPath,path, rsync_opts='-av --rsync-path="sudo /usr/bin/rsync --info=ALL --log-file=/home/ec2-user/transfer/rsync.log"', 
                      ssh_opts=ssh_opts, remote_to_local=False)
      for cert in configEnv['certs']:
        commandStr = f"sudo cat /etc/letsencrypt/live/{cert}/fullchain.pem /etc/letsencrypt/live/{cert}/privkey.pem >/home/u_name/etc/ssl/zettel.io/{cert}.pem"
        conn.local(commandStr)
        transfers.rsync(conn, "/home/u_name/etc/ssl/zettel.io/","/home/ec2-user/etc/ssl/zettel.io", rsync_opts='-av --rsync-path="sudo /usr/bin/rsync --info=ALL --log-file=/home/ec2-user/transfer/rsync.log"', 
                      ssh_opts=ssh_opts, remote_to_local=False)
        conn.run("cd /home/ec2-user/etc/ssl/zettel.io && ./mvCerts.sh")
      conn.sudo("sudo systemctl restart haproxy")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment