07070100000000000041ED000000000000000000000001610A952F00000000000000000000000000000000000000000000001F00000000openvpn-formula-0.1.2/metadata    07070100000001000081A4000000000000000000000001610A952F000019F1000000000000000000000000000000000000002800000000openvpn-formula-0.1.2/metadata/form.yml   openvpn:
  $type: namespace
  server:
    $type: namespace

    enabled:
      $type: boolean
      $default: True
      $help: Enable OpenVPN server.

    client_to_client:
      $type: boolean
      $default: false
      $name: Client-to-client communication
      $help: Allow communication between clients.

    duplicate_cn:
      $type: boolean
      $default: false
      $name: Duplicate CN
      $help: Allow multiple clients with the same common name.

    compression:
      $type: boolean
      $default: true
      $help: Enable LZ4 compression.

    max_clients:
      $type: number
      $help: Limit the number of allowed concurrent clients.

    verbosity:
      $type: number
      $default: 3
      $help: |
        Set verbosity level.

        0 -- No output except fatal errors.
        1 to 4 -- Normal usage range.
        5  --  Output R and W characters to the console for each packet read and write, uppercase is
        used for TCP/UDP packets and lowercase is used for TUN/TAP packets.
        6 to 11 -- Debug info range (see errlevel.h for additional information on debug levels).

    device:
      $type: select
      $default: tun
      $values:
        - tun
        - tap
      $help: |
        tun: OSI Layer 3 (IPv4/IPv6)
        tap: OSI Layer 2 (Ethernet)

    topology:
      $type: select
      $default: subnet
      $values:
        - subnet
        - gateway

    tls_auth:
      $type: boolean
      $default: true
      $help: Add an additional layer of HMAC authentication to mitigate DoS attacks.

    auth:
      $help: Use unix user account via PAM instead of client certificates.
      $name: Client Authentication via PAM
      $type: boolean

    bind:
      $type: group
      $help: Socket the server binds to.

      address:
        $default: 0.0.0.0
        $help: Only bind to hostname or IP address. Default is 0.0.0.0 (bind to all interfaces).

      port:
        $type: number
        $default: 1194
        $help: Listening port.

      protocol:
        $type: select
        $default: udp
        $help: Transport protocol. UDP is recommended for better performance.
        $values:
          - udp
          - tcp

    interface:
      $type: group
      $help: |
        VPN Network information. In gateway mode, this is used for the route.
        In subnet mode, this network is used to draw client IP addresses from.

      network:
        $type: text
        $default: 10.8.0.0

      netmask:
        $type: text
        $default: 255.255.255.0

    routes:
      $help: Additional routes to push to a client.
      $type: edit-group
      $itemName: Route ${i}
      $prototype:
        $type: group
        network:
          $type: text
        netmask:
          $type: text

    ssl:
      $type: group
      $help: Required SSL/TLS certificates and key file. When "Location" is set to "local", ensure the files are in present on the OpenVPN server system before applying the highstate!

      ca_group:
        $type: group
        $name: CA Certificate
        location:
          $help: Select a CA certificate on the OpenVPN server system or download one over HTTP(s)/FTP.
          $type: select
          $values:
            - local
            - remote
        file:
          $help: Path to the CA certificate on the OpenVPN server system.
          $visible: this.parent.value.location == "local"
          $default: "/etc/openvpn/ssl/ca.crt"
        url:
          $type: url
          $help: URL to the CA certificate (HTTP(s)/FTP are supported).
          $visible: this.parent.value.location == "remote"

      cert_group:
        $type: group
        $name: Server Certificate
        location:
          $help: Select a server certificate on the OpenVPN server system or download one over HTTP(s)/FTP.
          $type: select
          $values:
            - local
            - remote
        file:
          $help: Path to the server certificate on the OpenVPN server system.
          $visible: this.parent.value.location == "local"
          $default: "/etc/openvpn/ssl/server.crt"
        url:
          $type: url
          $help: URL to the server certificate (HTTP(s)/FTP are supported).
          $visible: this.parent.value.location == "remote"

      key_group:
        $type: group
        $name: Server Key
        location:
          $help: Select a server key on the OpenVPN server system or download one over HTTP(s)/FTP.
          $type: select
          $values:
            - local
            - remote
        file:
          $help: Path to the server key on the OpenVPN server system.
          $visible: this.parent.value.location == "local"
          $default: "/etc/openvpn/ssl/server.key"
        url:
          $type: url
          $help: URL to the server key (HTTP(s)/FTP are supported).
          $visible: this.parent.value.location == "remote"

      crl_group:
        $type: group
        $name: Client Revocation List (CRL)

        enabled:
          $help: Enable verification of revoked clients via a Certificate Revocation List (CRL).
          $type: boolean
        location:
          $help: Select a CRL on the OpenVPN server system or download one over HTTP(s)/FTP.
          $visible: this.parent.value.enabled == true
          $type: select
          $values:
            - local
            - remote
        file:
          $help: Path to the CRL on the OpenVPN server system.
          $visible: this.parent.value.enabled == true && this.parent.value.location == "local"
          $default: "/etc/openvpn/ssl/crl.pem"
        url:
          $type: url
          $help: URL to the CRL (HTTP(s)/FTP are supported).
          $visible: this.parent.value.enabled == true && this.parent.value.location == "remote"

    endpoint:
      $visible: this.parent.value.topology == "gateway"
      $type: group
      $name: Gateway Endpoint

      local:
        $type: text

      remote:
        $type: text

    dhcp_pool:
      $visible: this.parent.value.topology == "gateway"
      $type: group
      $name: Gateway DHCP-Pool

      start:
        $type: text

      end:
        $type: text

    redirect_gateway:
      $visible: this.parent.value.topology == "gateway"
      $type: boolean

    firewall:
      $type: group

      enabled:
        $type: boolean
        $name: Open Firewall Ports

      zone:
        $visible: this.parent.value.enabled == true
        $help: Which zone to open the port in. Uses the default firewalld zone if left empty.
        $default: public

      masquerade:
        $type: boolean
        $visible: this.parent.value.enabled == true
        $default: true
   07070100000002000081A4000000000000000000000001610A952F00000069000000000000000000000000000000000000002C00000000openvpn-formula-0.1.2/metadata/metadata.yml   description:
  Settings for OpenVPN server
group: general_system_configuration
after:
  - branch-network
   07070100000003000041ED000000000000000000000001610A952F00000000000000000000000000000000000000000000001E00000000openvpn-formula-0.1.2/openvpn 07070100000004000081A4000000000000000000000001610A952F00000235000000000000000000000000000000000000002E00000000openvpn-formula-0.1.2/openvpn-formula.changes -------------------------------------------------------------------
Fri Jul 16 07:36:14 UTC 2021 - Stefan Bluhm <stefan.bluhm@clacee.eu>

- Update to v0.1.2
- Changed package to noarch.

-------------------------------------------------------------------
Tue Aug 11 12:37:26 UTC 2020 - Alexander Graul <alexander.graul@suse.com>

- Update to v0.1.1
- Add hint that ssl certs must be on system (bsc#1172279)

-------------------------------------------------------------------
Mon Apr 27 14:35:26 UTC 2020 - Alexander Graul <agraul@suse.com>

- Initial Package v0.1
   07070100000005000081A4000000000000000000000001610A952F000009A9000000000000000000000000000000000000002B00000000openvpn-formula-0.1.2/openvpn-formula.spec    #
# spec file for package openvpn-formula
#
# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.

# Please submit bugfixes or comments via https://bugs.opensuse.org/
#


Name:           openvpn-formula
Version:        0.1.2
Release:        0
BuildArch:      noarch
Summary:        OpenVPN Salt Formula for Uyuni/SUSE Manager
License:        Apache-2.0
URL:            https://github.com/SUSE/salt-formulas/
Source:         %{name}-%{version}.tar.xz
Requires:       susemanager-sls

%description
OpenVPN Salt Formula for use in Uyuni/SUSE Manager.

%prep
%setup -q

%install
mkdir -p %{buildroot}/usr/share/susemanager/formulas/metadata/openvpn
mkdir -p %{buildroot}/usr/share/susemanager/formulas/states/openvpn
cp metadata/* %{buildroot}/usr/share/susemanager/formulas/metadata/openvpn/
cp -r openvpn/* %{buildroot}/usr/share/susemanager/formulas/states/openvpn/

%files
%dir /usr/share/susemanager
%dir /usr/share/susemanager/formulas
%dir /usr/share/susemanager/formulas/metadata
%dir /usr/share/susemanager/formulas/states
%dir /usr/share/susemanager/formulas/metadata/openvpn
%dir /usr/share/susemanager/formulas/states/openvpn
%dir /usr/share/susemanager/formulas/states/openvpn/server
%dir /usr/share/susemanager/formulas/states/openvpn/files
/usr/share/susemanager/formulas/metadata/openvpn/form.yml
/usr/share/susemanager/formulas/metadata/openvpn/metadata.yml
/usr/share/susemanager/formulas/states/openvpn/common.sls
/usr/share/susemanager/formulas/states/openvpn/init.sls
/usr/share/susemanager/formulas/states/openvpn/map.jinja
/usr/share/susemanager/formulas/states/openvpn/server/init.sls
/usr/share/susemanager/formulas/states/openvpn/server/service.sls
/usr/share/susemanager/formulas/states/openvpn/files/_gateway.conf
/usr/share/susemanager/formulas/states/openvpn/files/server.conf
/usr/share/susemanager/formulas/states/openvpn/files/_subnet.conf
/usr/share/susemanager/formulas/states/openvpn/files/ipp.txt

%changelog
   07070100000006000081A4000000000000000000000001610A952F00000282000000000000000000000000000000000000002900000000openvpn-formula-0.1.2/openvpn/common.sls  {% from "openvpn/map.jinja" import common with context %}

openvpn_packages:
  pkg.installed:
  - names: {{ common.pkgs }}

openvpn_ssl_dir:
  file.directory:
  - name: /etc/openvpn/ssl
  - require:
    - pkg: openvpn_packages



{%- if grains.os_family == "Arch" %}

{%- if pillar.openvpn.client is defined %}

{% from "openvpn/map.jinja" import client with context %}

{%- for tunnel_name, tunnel in client.tunnel.iteritems() %}

openvpn_service:
  service.running:
  - name: "{{ tunnel_name }}.service"
  - enable: true
  {%- if grains.get('noservices') %}
  - onlyif: /bin/false
  {%- endif %}
  
{%- endfor %}

{%- endif %}
{%- endif %}
  07070100000007000041ED000000000000000000000001610A952F00000000000000000000000000000000000000000000002400000000openvpn-formula-0.1.2/openvpn/files   07070100000008000081A4000000000000000000000001610A952F000001EC000000000000000000000000000000000000003200000000openvpn-formula-0.1.2/openvpn/files/_gateway.conf # Gateway settings
mode {{ server.get('mode', 'server') }}
{%- if server.get('mode', 'server') == 'server'}
tls-server
{%- endif %}

ifconfig {{ server.endpoint.local }} {{ server.endpoint.remote }}
ifconfig-pool {{ server.dhcp_pool.start }} {{ server.dhcp_pool.end }}

{%- if server.get('redirect_gateway', False) %}
push "redirect-gateway"
{%- else %}
;push "redirect-gateway"
{%- endif %}

route {{ server.interface.network }} {{ server.interface.netmask }}

{#-
    vim: syntax=jinja
-#}
07070100000009000081A4000000000000000000000001610A952F0000020B000000000000000000000000000000000000003100000000openvpn-formula-0.1.2/openvpn/files/_subnet.conf  # Configure server mode and supply a VPN subnet
# for OpenVPN to draw client addresses from.
# The server will take 10.8.0.1 for itself,
# the rest will be made available to clients.
# Each client will be able to reach the server
# on 10.8.0.1. Comment this line out if you are
# ethernet bridging. See the man page for more info.
topology {{ server.get('topology', 'subnet') }}
server {{ server.interface.network }} {{ server.interface.netmask }}

ifconfig-pool-persist /etc/openvpn/ipp.txt

{#-
    vim: syntax=jinja
-#}
 0707010000000A000081A4000000000000000000000001610A952F000000A7000000000000000000000000000000000000002C00000000openvpn-formula-0.1.2/openvpn/files/ipp.txt   {%- from "openvpn/map.jinja" import server with context %}{%- for client in server.interface.get('clients', []) %}
{{ client.name }},{{ client.address }}
{%- endfor %} 0707010000000B000081A4000000000000000000000001610A952F00000C94000000000000000000000000000000000000003000000000openvpn-formula-0.1.2/openvpn/files/server.conf   {%- from "openvpn/map.jinja" import server with context %}

local {{ server.bind.address }}
port {{ server.bind.port }}

# TCP or UDP server?
proto {{ server.bind.get('protocol', 'udp') }}

{%- if server.get('auth', False) %}
plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn
client-cert-not-required
{%- endif %}

# "dev tun" will create a routed IP tunnel,
# "dev tap" will create an ethernet tunnel.
dev {{ server.get('device', 'tun') }}

# SSL
ca {{ server.ssl.ca_group.get('file', '/etc/openvpn/ssl/ca.crt') }}
cert {{ server.ssl.cert_group.get('file', '/etc/openvpn/ssl/server.crt') }}
key {{ server.ssl.key_group.get('file', '/etc/openvpn/ssl/server.key') }}
dh /etc/openvpn/ssl/dh2048.pem
{%- if server.ssl.crl_group.get('enabled', False) %}
crl-verify {{ server.ssl.crl_group.get('file', '/etc/openvpn/ssl/crl.pem') }}
{%- endif %}


{%- if server.get('topology', 'subnet') == 'subnet' %}
{% include "openvpn/files/_subnet.conf" %}
{%- elif server.topology == 'gateway' %}
{% include "openvpn/files/_gateway.conf" %}
{%- endif %}

{%- for route in server.get('routes', []) %}
push "route {{ route.network }} {{ route.netmask }}"
{%- endfor %}

# Uncomment this directive to allow different
# clients to be able to "see" each other.
# By default, clients will only see the server.
# To force clients to only see the server, you
# will also need to appropriately firewall the
# server's TUN/TAP interface.
{%- if server.get("client_to_client", False) %}
client-to-client
{%- else %}
;client-to-client
{%- endif %}

# Uncomment this directive if multiple clients
# might connect with the same certificate/key
# files or common names.  This is recommended
# only for testing purposes.  For production use,
# each client should have its own certificate/key
# pair.
#
# IF YOU HAVE NOT GENERATED INDIVIDUAL
# CERTIFICATE/KEY PAIRS FOR EACH CLIENT,
# EACH HAVING ITS OWN UNIQUE "COMMON NAME",
# UNCOMMENT THIS LINE OUT.
{%- if server.get("duplicate_cn", False) %}
duplicate-cn
{%- else %}
;duplicate-cn
{%- endif %}

# The keepalive directive causes ping-like
# messages to be sent back and forth over
# the link so that each side knows when
# the other side has gone down.
# Ping every 10 seconds, assume that remote
# peer is down if no ping received during
# a 120 second time period.
keepalive 10 60
inactive 600

# For extra security beyond that provided
# by SSL/TLS, create an "HMAC firewall"
# to help block DoS attacks and UDP port flooding.
#
# Generate with:
#   openvpn --genkey --secret ta.key
#
# The server and each client must have
# a copy of this key.
# The second parameter should be '0'
# on the server and '1' on the clients.
{%- if server.get('tls_auth', False) %}
tls-auth ta.key 0
{%- else %}
;tls-auth ta.key 0
{%- endif %}

{%- if server.get('compression', True) %}
compress lz4-v2
push "compress lz4-v2"
{%- else %}
;compress lz4-v2
;push "compress lz4-v2"
{%- endif %}

{%- if server.get('max_clients', False) %}
max-clients {{ server.max_clients }}
{%- endif %}
user nobody
group nogroup

persist-key
persist-tun

;status openvpn-status.log
;log         openvpn.log
;log-append  openvpn.log

verb {{ server.get('verbosity', 3) }}
;mute 20

{#-
    vim: syntax=jinja
-#}
0707010000000C000081A4000000000000000000000001610A952F00000098000000000000000000000000000000000000002700000000openvpn-formula-0.1.2/openvpn/init.sls    
include:
{% if pillar.openvpn.server is defined %}
- openvpn.server
{% endif %}
{% if pillar.openvpn.client is defined %}
- openvpn.client
{% endif %}
0707010000000D000081A4000000000000000000000001610A952F00000531000000000000000000000000000000000000002800000000openvpn-formula-0.1.2/openvpn/map.jinja   {% set common = salt['grains.filter_by']({
    'Debian': {
        'pkgs': ['openvpn'],
        'service': 'openvpn',
        'config_dir': '/etc/openvpn',
    },
    'RedHat': {
        'pkgs': ['openvpn'],
        'service': 'openvpn',
        'config_dir': '/etc/openvpn',
    },
    'Suse': {
        'pkgs': ['openvpn'],
        'service': 'openvpn',
        'config_dir': '/etc/openvpn',
    },
    'Arch': {
        'pkgs': ['openvpn'],
        'service': 'openvpn',
        'config_dir': '/etc/openvpn',
    },
}, merge=salt['pillar.get']('openvpn')) %}

{% set client = salt['grains.filter_by']({
    'Debian': {
        'service_enabled': True,
        'tunnel': {},
        'pkipath': 'pki',
    },
    'RedHat': {
        'service_enabled': True,
        'tunnel': {},
    },
    'Suse': {
        'service_enabled': True,
        'tunnel': {},
    },
    'Arch': {
        'service_enabled': True,
        'tunnel': {},
    },
}, merge=salt['pillar.get']('openvpn:client')) %}

{% set server = salt['grains.filter_by']({
    'Debian': {
        'service_enabled': True,
        'pkipath': 'pki'
    },
    'RedHat': {
        'service_enabled': True,
    },
    'Suse': {
        'service_enabled': True,
    },
    'Arch': {
        'service_enabled': True,
    },
}, merge=salt['pillar.get']('openvpn:server')) %}
   0707010000000E000041ED000000000000000000000001610A952F00000000000000000000000000000000000000000000002500000000openvpn-formula-0.1.2/openvpn/server  0707010000000F000081A4000000000000000000000001610A952F00000022000000000000000000000000000000000000002E00000000openvpn-formula-0.1.2/openvpn/server/init.sls include:
- openvpn.server.service
  07070100000010000081A4000000000000000000000001610A952F000010EF000000000000000000000000000000000000003100000000openvpn-formula-0.1.2/openvpn/server/service.sls  {% from "openvpn/map.jinja" import server with context %}
{% from "openvpn/map.jinja" import common with context %}
{%- if server.enabled %}

include:
- openvpn.common

{%- if grains.get('virtual_subtype', None) not in ['Docker', 'LXC'] %}

net.ipv4.ip_forward:
  sysctl.present:
  - value: 1

{%- endif %}

/etc/openvpn/server.conf:
  file.managed:
  - source: salt://openvpn/files/server.conf
  - template: jinja
  - mode: 600
  - require:
    - pkg: openvpn_packages
  - watch_in:
    - service: openvpn_service

/etc/openvpn/ipp.txt:
  file.managed:
  - source: salt://openvpn/files/ipp.txt
  - template: jinja
  - mode: 600
  - require:
    - pkg: openvpn_packages
  - watch_in:
    - service: openvpn_service

{%- if server.ssl.get('key') %}
/etc/openvpn/ssl/server.key:
  file.managed:
    - contents_pillar: openvpn:server:ssl:key
    - mode: 600
    - watch_in:
      - service: openvpn_service
{%- endif %}

{%- if server.ssl.get('cert') %}
/etc/openvpn/ssl/server.crt:
  file.managed:
    - contents_pillar: openvpn:server:ssl:cert
    - watch_in:
      - service: openvpn_service
{%- endif %}

{%- if server.ssl.get('ca') %}
/etc/openvpn/ssl/ca.crt:
  file.managed:
    - contents_pillar: openvpn:server:ssl:ca
    - watch_in:
      - service: openvpn_service
{%- endif %}

{%- if server.ssl.ca_group.get("location", "local") == "remote" %}
/etc/openvpn/ssl/ca.crt:
  file.managed:
    - source: {{ server.ssl.ca_group.url }}
    - skip_verify: true
    - watch_in:
      - service: openvpn_service
{%- endif %}

{%- if server.ssl.cert_group.get("location", "local") == "remote" %}
/etc/openvpn/ssl/server.crt:
  file.managed:
    - source: {{ server.ssl.cert_group.url }}
    - skip_verify: true
    - watch_in:
      - service: openvpn_service
{%- endif %}

{%- if server.ssl.key_group.get("location", "local") == "remote" %}
/etc/openvpn/ssl/server.key:
  file.managed:
    - source: {{ server.ssl.key_group.url }}
    - skip_verify: true
    - watch_in:
      - service: openvpn_service
{%- endif %}

{%- if server.ssl.crl_group.get("enabled", False) %}
{%- if server.ssl.crl_group.get("location", "local") == "remote" %}
/etc/openvpn/ssl/crl.pem:
  file.managed:
    - source: {{ server.ssl.crl_group.url }}
    - skip_verify: true
    - watch_in:
      - service: openvpn_service
{%- endif %}
{%- endif %}


openvpn_generate_dhparams:
  cmd.run:
  - name: openssl dhparam -out /etc/openvpn/ssl/dh2048.pem 2048
  - creates: /etc/openvpn/ssl/dh2048.pem
  - watch_in:
    - service: openvpn_service

{%- if server.get('auth', False) %}
openvpn_auth_packages:
  pkg.installed:
    - name: openvpn-auth-pam-plugin

openvpn_auth_pam:
  file.symlink:
    - name: /etc/pam.d/openvpn
    - target: /etc/pam.d/common-auth
    - watch_in:
      - service: openvpn_service
    - require:
      - pkg: openvpn_auth_packages
{%- endif %}

{%- if server.get('tls_auth', False) %}
openvpn_generate_ta_key:
  cmd.run:
    - name: openvpn --genkey --secret /etc/openvpn/ta.key
    - creates: /etc/openvpn/ta.key
    - watch_in:
      - service: openvpn_service
{% endif %}

openvpn_service:
  service.running:
  {%- if grains.get('init', None) == 'systemd' %}
  - name: {{ common.service }}@server
  {%- else %}
  - name: {{ common.service }}
  {%- endif %}
  - enable: true
  {%- if grains.get('noservices') %}
  - onlyif: /bin/false
  {%- endif %}

{% if server.firewall.get('enabled', False) %}
firewalld.add_port:
  module.run:
    - zone: {{ server.firewall.get('zone', '') }}
    - force_masquerade: {{ server.firewall.get('masquerade', True) }}
    - port: {{ server.bind.port }}/{{ server.bind.protocol }}
firewalld.reload_rules:
  module.run:
    - require:
        - module: firewalld.add_port
{%- endif %}

{%- else %}

openvpn_service:
  service.dead:
    {%- if grains.get('init', None) == 'systemd' %}
    - name: {{ common.service }}@server
    {%- else %}
    - name: {{ common.service }}
    {%- endif %}
    - enable: false

{% if server.firewall.get('enabled', False) %}
firewalld.remove_port:
  module.run:
    - zone: {{ server.firewall.get('zone', 'public') }}
    - force_masquerade: {{ server.firewall.get('masquerade', True) }}
    - port: {{ server.bind.port }}/{{ server.bind.protocol }}
firewalld.reload_rules:
  module.run:
    - require:
        - module: firewalld.remove_port
{%- endif %}

{%- endif %}
 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!                                                                                                                            46 blocks
