├── revision ├── actions ├── pause ├── cleanup ├── resume ├── show-routers ├── restart-services ├── run-deferred-hooks ├── show-deferred-events ├── show-dhcp-networks ├── show-loadbalancers ├── openstack-upgrade ├── security-checklist ├── openstack_upgrade.py └── security_checklist.py ├── hooks ├── start ├── stop ├── install ├── config-changed ├── update-status ├── upgrade-charm ├── amqp-relation-changed ├── amqp-relation-joined ├── ha-relation-departed ├── ha-relation-joined ├── post-series-upgrade ├── pre-series-upgrade ├── amqp-nova-relation-changed ├── amqp-nova-relation-joined ├── amqp-relation-departed ├── charmhelpers │ ├── core │ │ ├── host_factory │ │ │ ├── __init__.py │ │ │ └── centos.py │ │ ├── kernel_factory │ │ │ ├── __init__.py │ │ │ ├── ubuntu.py │ │ │ └── centos.py │ │ ├── __init__.py │ │ ├── services │ │ │ └── __init__.py │ │ ├── files.py │ │ ├── kernel.py │ │ ├── sysctl.py │ │ └── hugepage.py │ ├── contrib │ │ ├── hardening │ │ │ ├── defaults │ │ │ │ ├── __init__.py │ │ │ │ ├── apache.yaml.schema │ │ │ │ ├── mysql.yaml.schema │ │ │ │ ├── apache.yaml │ │ │ │ ├── ssh.yaml.schema │ │ │ │ ├── os.yaml.schema │ │ │ │ ├── ssh.yaml │ │ │ │ ├── mysql.yaml │ │ │ │ └── os.yaml │ │ │ ├── host │ │ │ │ ├── templates │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── 99-hardening.sh │ │ │ │ │ ├── 99-juju-hardening.conf │ │ │ │ │ ├── 10.hardcore.conf │ │ │ │ │ ├── securetty │ │ │ │ │ ├── passwdqc.conf │ │ │ │ │ ├── pinerolo_profile.sh │ │ │ │ │ ├── tally2 │ │ │ │ │ └── modules │ │ │ │ ├── __init__.py │ │ │ │ └── checks │ │ │ │ │ ├── apt.py │ │ │ │ │ ├── securetty.py │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── minimize_access.py │ │ │ │ │ ├── profile.py │ │ │ │ │ ├── limits.py │ │ │ │ │ └── login.py │ │ │ ├── ssh │ │ │ │ ├── templates │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── ssh_config │ │ │ │ ├── __init__.py │ │ │ │ └── checks │ │ │ │ │ └── __init__.py │ │ │ ├── apache │ │ │ │ ├── templates │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── 99-hardening.conf │ │ │ │ │ └── alias.conf │ │ │ │ ├── __init__.py │ │ │ │ └── checks │ │ │ │ │ └── __init__.py │ │ │ ├── mysql │ │ │ │ ├── templates │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── hardening.cnf │ │ │ │ ├── __init__.py │ │ │ │ └── checks │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── config.py │ │ │ ├── __init__.py │ │ │ ├── README.hardening.md │ │ │ ├── audits │ │ │ │ └── __init__.py │ │ │ └── templating.py │ │ ├── openstack │ │ │ ├── templates │ │ │ │ ├── vendor_data.json │ │ │ │ ├── section-oslo-middleware │ │ │ │ ├── section-audit-middleware-notifications │ │ │ │ ├── section-oslo-cache │ │ │ │ ├── logrotate │ │ │ │ ├── section-filter-audit │ │ │ │ ├── section-oslo-messaging-rabbit │ │ │ │ ├── section-oslo-messaging-rabbit-ocata │ │ │ │ ├── section-keystone-authtoken-v3only │ │ │ │ ├── section-service-user │ │ │ │ ├── section-zeromq │ │ │ │ ├── section-keystone-authtoken-legacy │ │ │ │ ├── section-oslo-notifications │ │ │ │ ├── git.upstart │ │ │ │ ├── section-placement │ │ │ │ ├── section-keystone-authtoken │ │ │ │ ├── section-rabbitmq-oslo │ │ │ │ ├── __init__.py │ │ │ │ ├── ceph.conf │ │ │ │ ├── section-keystone-authtoken-mitaka │ │ │ │ ├── section-ceph-bluestore-compression │ │ │ │ ├── openstack_https_frontend │ │ │ │ ├── openstack_https_frontend.conf │ │ │ │ └── memcached.conf │ │ │ ├── ha │ │ │ │ └── __init__.py │ │ │ ├── __init__.py │ │ │ ├── files │ │ │ │ ├── __init__.py │ │ │ │ ├── check_haproxy_queue_depth.sh │ │ │ │ └── check_haproxy.sh │ │ │ ├── exceptions.py │ │ │ └── alternatives.py │ │ ├── __init__.py │ │ ├── hardware │ │ │ └── __init__.py │ │ ├── hahelpers │ │ │ ├── __init__.py │ │ │ └── apache.py │ │ ├── network │ │ │ ├── __init__.py │ │ │ └── ovs │ │ │ │ └── utils.py │ │ ├── storage │ │ │ ├── __init__.py │ │ │ └── linux │ │ │ │ ├── __init__.py │ │ │ │ ├── bcache.py │ │ │ │ └── loopback.py │ │ ├── charmsupport │ │ │ └── __init__.py │ │ └── python.py │ ├── fetch │ │ ├── python │ │ │ ├── __init__.py │ │ │ ├── version.py │ │ │ ├── debug.py │ │ │ └── rpdb.py │ │ ├── giturl.py │ │ └── bzrurl.py │ ├── payload │ │ ├── __init__.py │ │ ├── archive.py │ │ └── execd.py │ ├── cli │ │ ├── hookenv.py │ │ ├── host.py │ │ ├── commands.py │ │ ├── benchmark.py │ │ └── unitdata.py │ └── osplatform.py ├── cluster-relation-broken ├── cluster-relation-departed ├── amqp-nova-relation-departed ├── neutron-plugin-api-relation-broken ├── neutron-plugin-api-relation-changed ├── neutron-plugin-api-relation-departed ├── neutron-plugin-api-relation-joined ├── nrpe-external-master-relation-joined ├── nrpe-external-master-relation-changed ├── quantum-network-service-relation-broken └── quantum-network-service-relation-changed ├── .stestr.conf ├── files ├── neutron-ha-monitor.conf └── override.conf ├── bindep.txt ├── .gitreview ├── .zuul.yaml ├── templates ├── parts │ ├── agent │ ├── database │ └── rabbitmq ├── icehouse │ ├── dnsmasq.conf │ ├── lbaas_agent.ini │ ├── fwaas_driver.ini │ ├── vpn_agent.ini │ ├── metering_agent.ini │ ├── neutron.conf │ ├── dhcp_agent.ini │ ├── ml2_conf.ini │ ├── metadata_agent.ini │ ├── l3_agent.ini │ └── nova.conf ├── newton │ ├── fwaas_driver.ini │ ├── lbaas_agent.ini │ ├── l3_agent.ini │ └── nova.conf ├── stein │ ├── fwaas_driver.ini │ └── l3_agent.ini ├── ext-port.conf ├── kilo │ ├── fwaas_driver.ini │ ├── vpn_agent.ini │ ├── lbaas_agent.ini │ ├── neutron.conf │ └── nova.conf ├── mitaka │ ├── lbaas_agent.ini │ ├── openvswitch_agent.ini │ ├── neutron.conf │ ├── l3_agent.ini │ ├── dhcp_agent.ini │ └── nova.conf ├── os-charm-phy-nic-mtu.conf ├── queens │ ├── metadata_agent.ini │ ├── openvswitch_agent.ini │ └── l3_agent.ini ├── ocata │ ├── neutron.conf │ └── dhcp_agent.ini ├── juno │ ├── ml2_conf.ini │ └── l3_agent.ini ├── rocky │ └── l3_agent.ini ├── usr.bin.neutron-lbaas-agent ├── usr.bin.nova-api-metadata ├── usr.bin.neutron-metadata-agent ├── usr.bin.neutron-metering-agent ├── usr.bin.neutron-lbaasv2-agent ├── usr.bin.neutron-openvswitch-agent ├── usr.bin.neutron-dhcp-agent └── usr.bin.neutron-l3-agent ├── hardening.yaml ├── lib └── .keep ├── .gitignore ├── osci.yaml ├── copyright ├── rename.sh ├── charmcraft.yaml ├── .project ├── .pydevproject ├── charm-helpers-hooks.yaml ├── Makefile ├── setup.cfg ├── unit_tests ├── __init__.py └── test_actions_openstack_upgrade.py ├── requirements.txt ├── test-requirements.txt ├── metadata.yaml └── actions.yaml /revision: -------------------------------------------------------------------------------- 1 | 64 2 | -------------------------------------------------------------------------------- /actions/pause: -------------------------------------------------------------------------------- 1 | actions.py -------------------------------------------------------------------------------- /actions/cleanup: -------------------------------------------------------------------------------- 1 | cleanup.py -------------------------------------------------------------------------------- /actions/resume: -------------------------------------------------------------------------------- 1 | actions.py -------------------------------------------------------------------------------- /hooks/start: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/stop: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /actions/show-routers: -------------------------------------------------------------------------------- 1 | actions.py -------------------------------------------------------------------------------- /hooks/install: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /actions/restart-services: -------------------------------------------------------------------------------- 1 | actions.py -------------------------------------------------------------------------------- /actions/run-deferred-hooks: -------------------------------------------------------------------------------- 1 | actions.py -------------------------------------------------------------------------------- /actions/show-deferred-events: -------------------------------------------------------------------------------- 1 | actions.py -------------------------------------------------------------------------------- /actions/show-dhcp-networks: -------------------------------------------------------------------------------- 1 | actions.py -------------------------------------------------------------------------------- /actions/show-loadbalancers: -------------------------------------------------------------------------------- 1 | actions.py -------------------------------------------------------------------------------- /hooks/config-changed: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/update-status: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/upgrade-charm: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/amqp-relation-changed: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/amqp-relation-joined: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/ha-relation-departed: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/ha-relation-joined: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/post-series-upgrade: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/pre-series-upgrade: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /actions/openstack-upgrade: -------------------------------------------------------------------------------- 1 | openstack_upgrade.py -------------------------------------------------------------------------------- /actions/security-checklist: -------------------------------------------------------------------------------- 1 | security_checklist.py -------------------------------------------------------------------------------- /hooks/amqp-nova-relation-changed: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/amqp-nova-relation-joined: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/amqp-relation-departed: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/charmhelpers/core/host_factory/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hooks/cluster-relation-broken: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/cluster-relation-departed: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/amqp-nova-relation-departed: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/charmhelpers/core/kernel_factory/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/defaults/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hooks/neutron-plugin-api-relation-broken: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/neutron-plugin-api-relation-changed: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/neutron-plugin-api-relation-departed: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/neutron-plugin-api-relation-joined: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/nrpe-external-master-relation-joined: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/templates/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/ssh/templates/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hooks/nrpe-external-master-relation-changed: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/quantum-network-service-relation-broken: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /hooks/quantum-network-service-relation-changed: -------------------------------------------------------------------------------- 1 | neutron_hooks.py -------------------------------------------------------------------------------- /.stestr.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | test_path=./unit_tests 3 | top_dir=./ 4 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/apache/templates/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/mysql/templates/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/vendor_data.json: -------------------------------------------------------------------------------- 1 | {{ vendor_data_json }} -------------------------------------------------------------------------------- /files/neutron-ha-monitor.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | verbose=True 3 | #debug=True 4 | check_interval=8 5 | -------------------------------------------------------------------------------- /bindep.txt: -------------------------------------------------------------------------------- 1 | libffi-dev [platform:dpkg] 2 | libxml2-dev [platform:dpkg] 3 | libxslt1-dev [platform:dpkg] 4 | -------------------------------------------------------------------------------- /.gitreview: -------------------------------------------------------------------------------- 1 | [gerrit] 2 | host=review.opendev.org 3 | port=29418 4 | project=openstack/charm-neutron-gateway.git 5 | -------------------------------------------------------------------------------- /.zuul.yaml: -------------------------------------------------------------------------------- 1 | - project: 2 | templates: 3 | - openstack-python3-charm-jobs 4 | - openstack-cover-jobs 5 | -------------------------------------------------------------------------------- /templates/parts/agent: -------------------------------------------------------------------------------- 1 | {% if availability_zone -%} 2 | availability_zone = {{ availability_zone }} 3 | {% endif -%} 4 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/templates/99-hardening.sh: -------------------------------------------------------------------------------- 1 | TMOUT={{ tmout }} 2 | readonly TMOUT 3 | export TMOUT 4 | 5 | readonly HISTFILE 6 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-oslo-middleware: -------------------------------------------------------------------------------- 1 | [oslo_middleware] 2 | 3 | # Bug #1758675 4 | enable_proxy_headers_parsing = true 5 | 6 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-audit-middleware-notifications: -------------------------------------------------------------------------------- 1 | {% if audit_middleware -%} 2 | [audit_middleware_notifications] 3 | driver = log 4 | {% endif -%} -------------------------------------------------------------------------------- /files/override.conf: -------------------------------------------------------------------------------- 1 | # Override default Restart policy for nova-api-metadata to always 2 | # dealing with messaging timeout on startup with conductor services 3 | [Service] 4 | Restart=always -------------------------------------------------------------------------------- /hardening.yaml: -------------------------------------------------------------------------------- 1 | # Overrides file for contrib.hardening. See README.hardening in 2 | # contrib.hardening for info on how to use this file. 3 | ssh: 4 | server: 5 | use_pam: 'yes' # juju requires this 6 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-oslo-cache: -------------------------------------------------------------------------------- 1 | [cache] 2 | {% if memcache_url %} 3 | enabled = true 4 | backend = oslo_cache.memcache_pool 5 | memcache_servers = {{ memcache_url }} 6 | {% endif %} 7 | -------------------------------------------------------------------------------- /lib/.keep: -------------------------------------------------------------------------------- 1 | This file was created by release-tools to ensure that this empty 2 | directory is preserved in vcs re: lint check definitions in global 3 | tox.ini files. This file can be removed if/when this dir is actually in use. 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | .coverage 3 | tags 4 | .tox 5 | .testrepository 6 | .stestr 7 | *.pyc 8 | *.sw[nop] 9 | *.pyc 10 | precise 11 | trusty 12 | wily 13 | xenial 14 | .unit-state.db 15 | func-results.json 16 | __pycache__ 17 | *.charm 18 | -------------------------------------------------------------------------------- /templates/icehouse/dnsmasq.conf: -------------------------------------------------------------------------------- 1 | {%- if instance_mtu -%} 2 | dhcp-option=26,{{ instance_mtu }} 3 | {% endif -%} 4 | {% if dnsmasq_flags -%} 5 | {% for key, value in dnsmasq_flags.items() -%} 6 | {{ key }} = {{ value }} 7 | {% endfor -%} 8 | {% endif -%} 9 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/logrotate: -------------------------------------------------------------------------------- 1 | /var/log/{{ logrotate_logs_location }}/*.log { 2 | {{ logrotate_interval }} 3 | {{ logrotate_count }} 4 | compress 5 | delaycompress 6 | missingok 7 | notifempty 8 | copytruncate 9 | } 10 | -------------------------------------------------------------------------------- /osci.yaml: -------------------------------------------------------------------------------- 1 | - project: 2 | templates: 3 | - charm-unit-jobs-py310 4 | - charm-functional-jobs 5 | vars: 6 | needs_charm_build: true 7 | charm_build_name: neutron-gateway 8 | build_type: charmcraft 9 | charmcraft_channel: 3.x/beta 10 | -------------------------------------------------------------------------------- /templates/parts/database: -------------------------------------------------------------------------------- 1 | sql_connection = {{ database_type }}://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}{% if database_ssl_ca %}?ssl_ca={{ database_ssl_ca }}{% if database_ssl_cert %}&ssl_cert={{ database_ssl_cert }}&ssl_key={{ database_ssl_key }}{% endif %}{% endif %} 2 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-filter-audit: -------------------------------------------------------------------------------- 1 | {% if audit_middleware and service_name -%} 2 | [filter:audit] 3 | paste.filter_factory = keystonemiddleware.audit:filter_factory 4 | audit_map_file = /etc/{{ service_name }}/api_audit_map.conf 5 | service_name = {{ service_name }} 6 | {% endif -%} -------------------------------------------------------------------------------- /copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0 2 | 3 | Files: * 4 | Copyright: 2012, Canonical Ltd. 5 | License: GPL-3 6 | 7 | License: GPL-3 8 | On Debian GNU/Linux system you can find the complete text of the 9 | GPL-3 license in '/usr/share/common-licenses/GPL-3' 10 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-oslo-messaging-rabbit: -------------------------------------------------------------------------------- 1 | [oslo_messaging_rabbit] 2 | {% if rabbitmq_ha_queues -%} 3 | rabbit_ha_queues = True 4 | {% endif -%} 5 | {% if rabbit_ssl_port -%} 6 | ssl = True 7 | {% endif -%} 8 | {% if rabbit_ssl_ca -%} 9 | ssl_ca_file = {{ rabbit_ssl_ca }} 10 | {% endif -%} 11 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-oslo-messaging-rabbit-ocata: -------------------------------------------------------------------------------- 1 | [oslo_messaging_rabbit] 2 | {% if rabbitmq_ha_queues -%} 3 | rabbit_ha_queues = True 4 | {% endif -%} 5 | {% if rabbit_ssl_port -%} 6 | rabbit_use_ssl = True 7 | {% endif -%} 8 | {% if rabbit_ssl_ca -%} 9 | ssl_ca_file = {{ rabbit_ssl_ca }} 10 | {% endif -%} 11 | -------------------------------------------------------------------------------- /templates/icehouse/lbaas_agent.ini: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | periodic_interval = 10 3 | interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver 4 | ovs_use_veth = False 5 | device_driver = neutron.services.loadbalancer.drivers.haproxy.namespace_driver.HaproxyNSDriver 6 | [haproxy] 7 | loadbalancer_state_path = $state_path/lbaas 8 | user_group = nogroup 9 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-keystone-authtoken-v3only: -------------------------------------------------------------------------------- 1 | {% if auth_host -%} 2 | [keystone_authtoken] 3 | {% for option_name, option_value in keystone_authtoken.items() -%} 4 | {{ option_name }} = {{ option_value }} 5 | {% endfor -%} 6 | {% if use_memcache == true %} 7 | memcached_servers = {{ memcache_url }} 8 | {% endif -%} 9 | {% endif -%} 10 | -------------------------------------------------------------------------------- /rename.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | charm=$(grep "charm_build_name" osci.yaml | awk '{print $2}') 3 | echo "renaming ${charm}_*.charm to ${charm}.charm" 4 | echo -n "pwd: " 5 | pwd 6 | ls -al 7 | echo "Removing bad downloaded charm maybe?" 8 | if [[ -e "${charm}.charm" ]]; 9 | then 10 | rm "${charm}.charm" 11 | fi 12 | echo "Renaming charm here." 13 | mv ${charm}_*.charm ${charm}.charm 14 | -------------------------------------------------------------------------------- /templates/newton/fwaas_driver.ini: -------------------------------------------------------------------------------- 1 | # newton 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [fwaas] 7 | agent_version = v1 8 | driver = iptables 9 | enabled = True 10 | -------------------------------------------------------------------------------- /templates/stein/fwaas_driver.ini: -------------------------------------------------------------------------------- 1 | # stein 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [fwaas] 7 | agent_version = v2 8 | driver = iptables_v2 9 | enabled = True 10 | -------------------------------------------------------------------------------- /charmcraft.yaml: -------------------------------------------------------------------------------- 1 | type: charm 2 | 3 | parts: 4 | charm: 5 | plugin: dump 6 | source: . 7 | 8 | base: ubuntu@24.04 9 | platforms: 10 | amd64: 11 | build-on: amd64 12 | build-for: amd64 13 | arm64: 14 | build-on: arm64 15 | build-for: arm64 16 | ppc64el: 17 | build-on: ppc64el 18 | build-for: ppc64el 19 | s390x: 20 | build-on: s390x 21 | build-for: s390x 22 | -------------------------------------------------------------------------------- /templates/icehouse/fwaas_driver.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [fwaas] 6 | driver = neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver 7 | enabled = True 8 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/defaults/apache.yaml.schema: -------------------------------------------------------------------------------- 1 | # NOTE: this schema must contain all valid keys from it's associated defaults 2 | # file. It is used to validate user-provided overrides. 3 | common: 4 | apache_dir: 5 | traceenable: 6 | 7 | hardening: 8 | allowed_http_methods: 9 | modules_to_disable: 10 | servertokens: 11 | honor_cipher_order: 12 | cipher_suite: 13 | -------------------------------------------------------------------------------- /templates/ext-port.conf: -------------------------------------------------------------------------------- 1 | description "Enabling Quantum external networking port" 2 | 3 | start on runlevel [2345] 4 | 5 | task 6 | 7 | script 8 | EXT_PORT="{{ ext_port }}" 9 | MTU="{{ ext_port_mtu }}" 10 | if [ -n "$EXT_PORT" ]; then 11 | ip link set $EXT_PORT up 12 | if [ -n "$MTU" ]; then 13 | ip link set $EXT_PORT mtu $MTU 14 | fi 15 | fi 16 | end script 17 | -------------------------------------------------------------------------------- /templates/kilo/fwaas_driver.ini: -------------------------------------------------------------------------------- 1 | # kilo 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [fwaas] 7 | driver = neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver 8 | enabled = True 9 | -------------------------------------------------------------------------------- /templates/icehouse/vpn_agent.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [vpnagent] 6 | vpn_device_driver=neutron.services.vpn.device_drivers.ipsec.OpenSwanDriver 7 | [ipsec] 8 | ipsec_status_check_interval=60 9 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/templates/99-juju-hardening.conf: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # WARNING: This configuration file is maintained by Juju. Local changes may 3 | # be overwritten. 4 | ############################################################################### 5 | {% for key, value in sysctl_settings -%} 6 | {{ key }}={{ value }} 7 | {% endfor -%} 8 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-service-user: -------------------------------------------------------------------------------- 1 | {% if auth_host -%} 2 | [service_user] 3 | send_service_user_token = true 4 | auth_type = password 5 | auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }} 6 | project_domain_name = service_domain 7 | user_domain_name = service_domain 8 | project_name = {{ admin_tenant_name }} 9 | username = {{ admin_user }} 10 | password = {{ admin_password }} 11 | {% endif -%} 12 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | neutron-gateway 4 | 5 | 6 | 7 | 8 | 9 | org.python.pydev.PyDevBuilder 10 | 11 | 12 | 13 | 14 | 15 | org.python.pydev.pythonNature 16 | 17 | 18 | -------------------------------------------------------------------------------- /templates/kilo/vpn_agent.ini: -------------------------------------------------------------------------------- 1 | # kilo 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [vpnagent] 7 | vpn_device_driver=neutron_vpnaas.services.vpn.device_drivers.ipsec.OpenSwanDriver 8 | [ipsec] 9 | ipsec_status_check_interval=60 10 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-zeromq: -------------------------------------------------------------------------------- 1 | {% if zmq_host -%} 2 | # ZeroMQ configuration (restart-nonce: {{ zmq_nonce }}) 3 | rpc_backend = zmq 4 | rpc_zmq_host = {{ zmq_host }} 5 | {% if zmq_redis_address -%} 6 | rpc_zmq_matchmaker = redis 7 | matchmaker_heartbeat_freq = 15 8 | matchmaker_heartbeat_ttl = 30 9 | [matchmaker_redis] 10 | host = {{ zmq_redis_address }} 11 | {% else -%} 12 | rpc_zmq_matchmaker = ring 13 | {% endif -%} 14 | {% endif -%} 15 | -------------------------------------------------------------------------------- /hooks/charmhelpers/core/kernel_factory/ubuntu.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | 4 | def persistent_modprobe(module): 5 | """Load a kernel module and configure for auto-load on reboot.""" 6 | with open('/etc/modules', 'r+') as modules: 7 | if module not in modules.read(): 8 | modules.write(module + "\n") 9 | 10 | 11 | def update_initramfs(version='all'): 12 | """Updates an initramfs image.""" 13 | return subprocess.check_call(["update-initramfs", "-k", version, "-u"]) 14 | -------------------------------------------------------------------------------- /.pydevproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | python 2.7 4 | Default 5 | 6 | /neutron-gateway/hooks 7 | /neutron-gateway/unit_tests 8 | 9 | 10 | -------------------------------------------------------------------------------- /charm-helpers-hooks.yaml: -------------------------------------------------------------------------------- 1 | repo: https://github.com/juju/charm-helpers 2 | destination: hooks/charmhelpers 3 | include: 4 | - core 5 | - osplatform 6 | - cli 7 | - fetch 8 | - contrib.openstack|inc=* 9 | - contrib.hardware.pci 10 | - contrib.hahelpers 11 | - contrib.network 12 | - contrib.python 13 | - contrib.storage.linux 14 | - contrib.python 15 | - payload 16 | - contrib.charmsupport 17 | - contrib.hardening|inc=* 18 | - contrib.openstack.policyd 19 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/defaults/mysql.yaml.schema: -------------------------------------------------------------------------------- 1 | # NOTE: this schema must contain all valid keys from it's associated defaults 2 | # file. It is used to validate user-provided overrides. 3 | hardening: 4 | mysql-conf: 5 | hardening-conf: 6 | security: 7 | chroot: 8 | safe-user-create: 9 | secure-auth: 10 | skip-symbolic-links: 11 | skip-show-database: 12 | local-infile: 13 | allow-suspicious-udfs: 14 | automatic-sp-privileges: 15 | secure-file-priv: 16 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/templates/10.hardcore.conf: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # WARNING: This configuration file is maintained by Juju. Local changes may 3 | # be overwritten. 4 | ############################################################################### 5 | {% if disable_core_dump -%} 6 | # Prevent core dumps for all users. These are usually only needed by developers and may contain sensitive information. 7 | * hard core 0 8 | {% endif %} -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/templates/securetty: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # WARNING: This configuration file is maintained by Juju. Local changes may 3 | # be overwritten. 4 | ############################################################################### 5 | # A list of TTYs, from which root can log in 6 | # see `man securetty` for reference 7 | {% if ttys -%} 8 | {% for tty in ttys -%} 9 | {{ tty }} 10 | {% endfor -%} 11 | {% endif -%} 12 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-keystone-authtoken-legacy: -------------------------------------------------------------------------------- 1 | {% if auth_host -%} 2 | [keystone_authtoken] 3 | # Juno specific config (Bug #1557223) 4 | auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/{{ service_admin_prefix }} 5 | identity_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }} 6 | admin_tenant_name = {{ admin_tenant_name }} 7 | admin_user = {{ admin_user }} 8 | admin_password = {{ admin_password }} 9 | signing_dir = {{ signing_dir }} 10 | {% endif -%} 11 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-oslo-notifications: -------------------------------------------------------------------------------- 1 | {% if transport_url -%} 2 | [oslo_messaging_notifications] 3 | driver = {{ oslo_messaging_driver }} 4 | transport_url = {{ transport_url }} 5 | {% if send_notifications_to_logs %} 6 | driver = log 7 | {% endif %} 8 | {% if notification_topics -%} 9 | topics = {{ notification_topics }} 10 | {% endif -%} 11 | {% if notification_format -%} 12 | [notifications] 13 | notification_format = {{ notification_format }} 14 | {% endif -%} 15 | {% endif -%} 16 | -------------------------------------------------------------------------------- /templates/newton/lbaas_agent.ini: -------------------------------------------------------------------------------- 1 | # newton 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | interface_driver = openvswitch 8 | device_driver = neutron_lbaas.drivers.haproxy.namespace_driver.HaproxyNSDriver 9 | [haproxy] 10 | loadbalancer_state_path = $state_path/lbaas 11 | user_group = nogroup 12 | -------------------------------------------------------------------------------- /templates/icehouse/metering_agent.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [DEFAULT] 6 | driver = neutron.services.metering.drivers.iptables.iptables_driver.IptablesMeteringDriver 7 | measure_interval = 30 8 | report_interval = 300 9 | interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver 10 | use_namespaces = True 11 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/templates/passwdqc.conf: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # WARNING: This configuration file is maintained by Juju. Local changes may 3 | # be overwritten. 4 | ############################################################################### 5 | Name: passwdqc password strength enforcement 6 | Default: yes 7 | Priority: 1024 8 | Conflicts: cracklib 9 | Password-Type: Primary 10 | Password: 11 | requisite pam_passwdqc.so {{ auth_pam_passwdqc_options }} 12 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/templates/pinerolo_profile.sh: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # WARNING: This configuration file is maintained by Juju. Local changes may 3 | # be overwritten. 4 | ############################################################################### 5 | # Disable core dumps via soft limits for all users. Compliance to this setting 6 | # is voluntary and can be modified by users up to a hard limit. This setting is 7 | # a sane default. 8 | ulimit -S -c 0 > /dev/null 2>&1 9 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/mysql/templates/hardening.cnf: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # WARNING: This configuration file is maintained by Juju. Local changes may 3 | # be overwritten. 4 | ############################################################################### 5 | [mysqld] 6 | {% for setting, value in mysql_settings -%} 7 | {% if value == 'True' -%} 8 | {{ setting }} 9 | {% elif value != 'None' and value != None -%} 10 | {{ setting }} = {{ value }} 11 | {% endif -%} 12 | {% endfor -%} 13 | -------------------------------------------------------------------------------- /templates/mitaka/lbaas_agent.ini: -------------------------------------------------------------------------------- 1 | # kilo 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | periodic_interval = 10 8 | interface_driver = openvswitch 9 | ovs_use_veth = False 10 | device_driver = neutron_lbaas.services.loadbalancer.drivers.haproxy.namespace_driver.HaproxyNSDriver 11 | [haproxy] 12 | loadbalancer_state_path = $state_path/lbaas 13 | user_group = nogroup 14 | -------------------------------------------------------------------------------- /templates/kilo/lbaas_agent.ini: -------------------------------------------------------------------------------- 1 | # kilo 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | periodic_interval = 10 8 | interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver 9 | ovs_use_veth = False 10 | device_driver = neutron_lbaas.services.loadbalancer.drivers.haproxy.namespace_driver.HaproxyNSDriver 11 | [haproxy] 12 | loadbalancer_state_path = $state_path/lbaas 13 | user_group = nogroup 14 | -------------------------------------------------------------------------------- /templates/os-charm-phy-nic-mtu.conf: -------------------------------------------------------------------------------- 1 | description "Enabling Quantum external networking port" 2 | 3 | start on runlevel [2345] 4 | 5 | task 6 | 7 | script 8 | devs="{{ devs }}" 9 | mtu="{{ mtu }}" 10 | if [ -n "$mtu" ]; then 11 | tmpfile=`mktemp` 12 | echo $devs > $tmpfile 13 | while read -r dev; do 14 | [ -n "$dev" ] || continue 15 | rc=0 16 | # Try all devices before exiting with error 17 | ip link set $dev mtu $mtu || rc=$? 18 | done < $tmpfile 19 | rm $tmpfile 20 | [ $rc = 0 ] || exit $rc 21 | fi 22 | end script 23 | -------------------------------------------------------------------------------- /hooks/charmhelpers/core/kernel_factory/centos.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import os 3 | 4 | 5 | def persistent_modprobe(module): 6 | """Load a kernel module and configure for auto-load on reboot.""" 7 | if not os.path.exists('/etc/rc.modules'): 8 | open('/etc/rc.modules', 'a') 9 | os.chmod('/etc/rc.modules', 111) 10 | with open('/etc/rc.modules', 'r+') as modules: 11 | if module not in modules.read(): 12 | modules.write('modprobe %s\n' % module) 13 | 14 | 15 | def update_initramfs(version='all'): 16 | """Updates an initramfs image.""" 17 | return subprocess.check_call(["dracut", "-f", version]) 18 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/git.upstart: -------------------------------------------------------------------------------- 1 | description "{{ service_description }}" 2 | author "Juju {{ service_name }} Charm " 3 | 4 | start on runlevel [2345] 5 | stop on runlevel [!2345] 6 | 7 | respawn 8 | 9 | exec start-stop-daemon --start --chuid {{ user_name }} \ 10 | --chdir {{ start_dir }} --name {{ process_name }} \ 11 | --exec {{ executable_name }} -- \ 12 | {% for config_file in config_files -%} 13 | --config-file={{ config_file }} \ 14 | {% endfor -%} 15 | {% if log_file -%} 16 | --log-file={{ log_file }} 17 | {% endif -%} 18 | -------------------------------------------------------------------------------- /hooks/charmhelpers/core/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardware/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/ha/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /hooks/charmhelpers/fetch/python/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2019 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hahelpers/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/templates/tally2: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # WARNING: This configuration file is maintained by Juju. Local changes may 3 | # be overwritten. 4 | ############################################################################### 5 | Name: tally2 lockout after failed attempts enforcement 6 | Default: yes 7 | Priority: 1024 8 | Conflicts: cracklib 9 | Auth-Type: Primary 10 | Auth-Initial: 11 | required pam_tally2.so deny={{ auth_retries }} onerr=fail unlock_time={{ auth_lockout_time }} 12 | Account-Type: Primary 13 | Account-Initial: 14 | required pam_tally2.so 15 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/network/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/storage/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /templates/parts/rabbitmq: -------------------------------------------------------------------------------- 1 | {% if rabbitmq_host or rabbitmq_hosts -%} 2 | rabbit_userid = {{ rabbitmq_user }} 3 | rabbit_virtual_host = {{ rabbitmq_virtual_host }} 4 | rabbit_password = {{ rabbitmq_password }} 5 | {% if rabbitmq_hosts -%} 6 | rabbit_hosts = {{ rabbitmq_hosts }} 7 | {% if rabbitmq_ha_queues -%} 8 | rabbit_ha_queues = True 9 | rabbit_durable_queues = False 10 | {% endif -%} 11 | {% else -%} 12 | rabbit_host = {{ rabbitmq_host }} 13 | {% endif -%} 14 | {% if rabbit_ssl_port -%} 15 | rabbit_use_ssl = True 16 | rabbit_port = {{ rabbit_ssl_port }} 17 | {% if rabbit_ssl_ca -%} 18 | kombu_ssl_ca_certs = {{ rabbit_ssl_ca }} 19 | {% endif -%} 20 | {% endif -%} 21 | {% endif -%} -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make 2 | PYTHON := /usr/bin/env python3 3 | 4 | lint: 5 | @tox -e pep8 6 | 7 | test: 8 | @echo Starting unit tests... 9 | @tox -e py27 10 | 11 | functional_test: 12 | @echo Starting Zaza tests... 13 | @tox -e func 14 | 15 | bin/charm_helpers_sync.py: 16 | @mkdir -p bin 17 | @curl -o bin/charm_helpers_sync.py https://raw.githubusercontent.com/juju/charm-helpers/master/tools/charm_helpers_sync/charm_helpers_sync.py 18 | 19 | 20 | sync: bin/charm_helpers_sync.py 21 | @$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-hooks.yaml 22 | 23 | publish: lint test 24 | bzr push lp:charms/neutron-gateway 25 | bzr push lp:charms/trusty/neutron-gateway 26 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/charmsupport/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/storage/linux/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-placement: -------------------------------------------------------------------------------- 1 | [placement] 2 | {% if auth_host -%} 3 | auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }} 4 | auth_type = password 5 | {% if api_version == "3" -%} 6 | project_domain_name = {{ admin_domain_name }} 7 | user_domain_name = {{ admin_domain_name }} 8 | {% else -%} 9 | project_domain_name = default 10 | user_domain_name = default 11 | {% endif -%} 12 | project_name = {{ admin_tenant_name }} 13 | username = {{ admin_user }} 14 | password = {{ admin_password }} 15 | {% endif -%} 16 | {% if region -%} 17 | os_region_name = {{ region }} 18 | region_name = {{ region }} 19 | {% endif -%} 20 | randomize_allocation_candidates = true 21 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/defaults/apache.yaml: -------------------------------------------------------------------------------- 1 | # NOTE: this file contains the default configuration for the 'apache' hardening 2 | # code. If you want to override any settings you must add them to a file 3 | # called hardening.yaml in the root directory of your charm using the 4 | # name 'apache' as the root key followed by any of the following with new 5 | # values. 6 | 7 | common: 8 | apache_dir: '/etc/apache2' 9 | 10 | hardening: 11 | traceenable: 'off' 12 | allowed_http_methods: "GET POST" 13 | modules_to_disable: [ cgi, cgid ] 14 | servertokens: 'Prod' 15 | honor_cipher_order: 'on' 16 | cipher_suite: 'ALL:+MEDIUM:+HIGH:!LOW:!MD5:!RC4:!eNULL:!aNULL:!3DES' 17 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-keystone-authtoken: -------------------------------------------------------------------------------- 1 | {% if auth_host -%} 2 | [keystone_authtoken] 3 | auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }} 4 | auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }} 5 | auth_plugin = password 6 | project_domain_id = default 7 | user_domain_id = default 8 | project_name = {{ admin_tenant_name }} 9 | username = {{ admin_user }} 10 | password = {{ admin_password }} 11 | signing_dir = {{ signing_dir }} 12 | {% if service_type -%} 13 | service_type = {{ service_type }} 14 | {% endif -%} 15 | {% if admin_role -%} 16 | service_token_roles = {{ admin_role }} 17 | service_token_roles_required = True 18 | {% endif -%} 19 | {% endif -%} 20 | -------------------------------------------------------------------------------- /hooks/charmhelpers/core/services/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .base import * # NOQA 16 | from .helpers import * # NOQA 17 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-rabbitmq-oslo: -------------------------------------------------------------------------------- 1 | {% if rabbitmq_host or rabbitmq_hosts -%} 2 | [oslo_messaging_rabbit] 3 | rabbit_userid = {{ rabbitmq_user }} 4 | rabbit_virtual_host = {{ rabbitmq_virtual_host }} 5 | rabbit_password = {{ rabbitmq_password }} 6 | {% if rabbitmq_hosts -%} 7 | rabbit_hosts = {{ rabbitmq_hosts }} 8 | {% if rabbitmq_ha_queues -%} 9 | rabbit_ha_queues = True 10 | rabbit_durable_queues = False 11 | {% endif -%} 12 | {% else -%} 13 | rabbit_host = {{ rabbitmq_host }} 14 | {% endif -%} 15 | {% if rabbit_ssl_port -%} 16 | rabbit_use_ssl = True 17 | rabbit_port = {{ rabbit_ssl_port }} 18 | {% if rabbit_ssl_ca -%} 19 | kombu_ssl_ca_certs = {{ rabbit_ssl_ca }} 20 | {% endif -%} 21 | {% endif -%} 22 | {% endif -%} 23 | -------------------------------------------------------------------------------- /hooks/charmhelpers/payload/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | "Tools for working with files injected into a charm just before deployment." 16 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from os import path 16 | 17 | TEMPLATES_DIR = path.join(path.dirname(__file__), 'templates') 18 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/ssh/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from os import path 16 | 17 | TEMPLATES_DIR = path.join(path.dirname(__file__), 'templates') 18 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/apache/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from os import path 16 | 17 | TEMPLATES_DIR = path.join(path.dirname(__file__), 'templates') 18 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/mysql/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from os import path 16 | 17 | TEMPLATES_DIR = path.join(path.dirname(__file__), 'templates') 18 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/files/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # dummy __init__.py to fool syncer into thinking this is a syncable python 16 | # module 17 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # dummy __init__.py to fool syncer into thinking this is a syncable python 16 | # module 17 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = charm-neutron-gateway 3 | summary = Charm module for OpenStack Neutron 4 | description_file = 5 | README.md 6 | author = OpenStack 7 | author_email = openstack-discuss@lists.openstack.org 8 | home_page = https://docs.openstack.org/charm-guide/latest/ 9 | classifier = 10 | Intended Audience :: Developers 11 | Intended Audience :: System Administrators 12 | License :: OSI Approved :: Apache Software License 13 | Operating System :: POSIX :: Linux 14 | Programming Language :: Python 15 | Programming Language :: Python :: 3 16 | Programming Language :: Python :: 3.5 17 | Programming Language :: Python :: 3.6 18 | Programming Language :: Python :: 3.7 19 | 20 | [nosetests] 21 | verbosity=1 22 | with-coverage=1 23 | cover-erase=1 24 | cover-package=hooks 25 | -------------------------------------------------------------------------------- /templates/icehouse/neutron.conf: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [DEFAULT] 6 | verbose = {{ verbose }} 7 | debug = {{ debug }} 8 | lock_path = /var/lock/neutron 9 | core_plugin = {{ core_plugin }} 10 | {% include "parts/rabbitmq" %} 11 | control_exchange = neutron 12 | notification_driver = messaging 13 | {% if network_device_mtu -%} 14 | network_device_mtu = {{ network_device_mtu }} 15 | {% endif -%} 16 | api_workers = {{ workers }} 17 | rpc_response_timeout = {{ rpc_response_timeout }} 18 | 19 | [agent] 20 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 21 | report_interval = {{ report_interval }} 22 | -------------------------------------------------------------------------------- /templates/mitaka/openvswitch_agent.ini: -------------------------------------------------------------------------------- 1 | # mitaka 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [ovs] 7 | enable_tunneling = True 8 | local_ip = {{ local_ip }} 9 | bridge_mappings = {{ bridge_mappings }} 10 | 11 | [agent] 12 | tunnel_types = {{ overlay_network_type }} 13 | l2_population = {{ l2_population }} 14 | enable_distributed_routing = {{ enable_dvr }} 15 | {% if veth_mtu -%} 16 | veth_mtu = {{ veth_mtu }} 17 | {% endif -%} 18 | {% if extension_drivers -%} 19 | extensions = {{ extension_drivers }} 20 | {% endif %} 21 | 22 | [securitygroup] 23 | firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver 24 | -------------------------------------------------------------------------------- /templates/queens/metadata_agent.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | # Metadata service seems to cache neutron api url from keystone so trigger 6 | # restart if it changes: {{ quantum_url }} 7 | [DEFAULT] 8 | root_helper = sudo neutron-rootwrap /etc/neutron/rootwrap.conf 9 | state_path = /var/lib/neutron 10 | # Gateway runs a metadata API server locally 11 | nova_metadata_host = {{ nova_metadata_host }} 12 | nova_metadata_port = {{ nova_metadata_port }} 13 | nova_metadata_protocol = {{ nova_metadata_protocol }} 14 | metadata_proxy_shared_secret = {{ shared_secret }} 15 | cache_url = memory://?default_ttl=5 16 | metadata_workers = {{ workers }} 17 | -------------------------------------------------------------------------------- /templates/kilo/neutron.conf: -------------------------------------------------------------------------------- 1 | # kilo 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | verbose = {{ verbose }} 8 | debug = {{ debug }} 9 | core_plugin = {{ core_plugin }} 10 | control_exchange = neutron 11 | notification_driver = messaging 12 | {% if network_device_mtu -%} 13 | network_device_mtu = {{ network_device_mtu }} 14 | {% endif -%} 15 | api_workers = {{ workers }} 16 | rpc_response_timeout = {{ rpc_response_timeout }} 17 | 18 | [agent] 19 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 20 | report_interval = {{ report_interval }} 21 | 22 | {% include "section-rabbitmq-oslo" %} 23 | 24 | [oslo_concurrency] 25 | lock_path = /var/lock/neutron 26 | -------------------------------------------------------------------------------- /templates/queens/openvswitch_agent.ini: -------------------------------------------------------------------------------- 1 | # queens 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [ovs] 7 | enable_tunneling = True 8 | local_ip = {{ local_ip }} 9 | bridge_mappings = {{ bridge_mappings }} 10 | {%- if ovsdb_timeout and ovsdb_timeout > 0 %} 11 | ovsdb_timeout = {{ovsdb_timeout}} 12 | {%- endif %} 13 | 14 | [agent] 15 | tunnel_types = {{ overlay_network_type }} 16 | l2_population = {{ l2_population }} 17 | enable_distributed_routing = {{ enable_dvr }} 18 | {% if veth_mtu -%} 19 | veth_mtu = {{ veth_mtu }} 20 | {% endif -%} 21 | {% if extension_drivers -%} 22 | extensions = {{ extension_drivers }} 23 | {% endif %} 24 | 25 | [securitygroup] 26 | firewall_driver = {{ firewall_driver }} 27 | -------------------------------------------------------------------------------- /templates/mitaka/neutron.conf: -------------------------------------------------------------------------------- 1 | # mitaka 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | verbose = {{ verbose }} 8 | debug = {{ debug }} 9 | core_plugin = {{ core_plugin }} 10 | {% if network_device_mtu -%} 11 | network_device_mtu = {{ network_device_mtu }} 12 | {% endif -%} 13 | api_workers = {{ workers }} 14 | rpc_response_timeout = {{ rpc_response_timeout }} 15 | 16 | [agent] 17 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 18 | report_interval = {{ report_interval }} 19 | {% include "parts/agent" %} 20 | 21 | {% include "section-rabbitmq-oslo" %} 22 | 23 | {% include "section-oslo-notifications" %} 24 | 25 | [oslo_concurrency] 26 | lock_path = /var/lock/neutron 27 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/python.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2019 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # deprecated aliases for backwards compatibility 16 | from charmhelpers.fetch.python import debug # noqa 17 | from charmhelpers.fetch.python import packages # noqa 18 | from charmhelpers.fetch.python import rpdb # noqa 19 | from charmhelpers.fetch.python import version # noqa 20 | -------------------------------------------------------------------------------- /hooks/charmhelpers/cli/hookenv.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from . import cmdline 16 | from charmhelpers.core import hookenv 17 | 18 | 19 | cmdline.subcommand('relation-id')(hookenv.relation_id._wrapped) 20 | cmdline.subcommand('service-name')(hookenv.service_name) 21 | cmdline.subcommand('remote-service-name')(hookenv.remote_service_name._wrapped) 22 | -------------------------------------------------------------------------------- /unit_tests/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | from unittest.mock import patch 5 | 6 | _path = os.path.dirname(os.path.realpath(__file__)) 7 | _hooks = os.path.abspath(os.path.join(_path, '../hooks')) 8 | _actions = os.path.abspath(os.path.join(_path, '../actions')) 9 | _unit_tests = os.path.abspath(os.path.join(_path, '../unit_tests')) 10 | 11 | 12 | def _add_path(path): 13 | if path not in sys.path: 14 | sys.path.insert(1, path) 15 | 16 | 17 | _add_path(_hooks) 18 | _add_path(_actions) 19 | _add_path(_unit_tests) 20 | 21 | # Patch out lsb_release() and get_platform() as unit tests should be fully 22 | # insulated from the underlying platform. Unit tests assume that the system is 23 | # ubuntu jammy. 24 | patch( 25 | 'charmhelpers.osplatform.get_platform', return_value='ubuntu' 26 | ).start() 27 | patch( 28 | 'charmhelpers.core.host.lsb_release', 29 | return_value={ 30 | 'DISTRIB_CODENAME': 'jammy' 31 | }).start() 32 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/ceph.conf: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # ceph configuration file maintained by Juju 4 | # local changes may be overwritten. 5 | ############################################################################### 6 | [global] 7 | {% if auth -%} 8 | auth_supported = {{ auth }} 9 | keyring = /etc/ceph/$cluster.$name.keyring 10 | mon host = {{ mon_hosts }} 11 | {% endif -%} 12 | log to syslog = {{ use_syslog }} 13 | err to syslog = {{ use_syslog }} 14 | clog to syslog = {{ use_syslog }} 15 | {% if rbd_features %} 16 | rbd default features = {{ rbd_features }} 17 | {% endif %} 18 | 19 | [client] 20 | {% if rbd_client_cache_settings -%} 21 | {% for key, value in rbd_client_cache_settings.items() -%} 22 | {{ key }} = {{ value }} 23 | {% endfor -%} 24 | {%- endif %} 25 | 26 | {% if rbd_default_data_pool -%} 27 | rbd default data pool = {{ rbd_default_data_pool }} 28 | {% endif %} 29 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | 16 | class OSContextError(Exception): 17 | """Raised when an error occurs during context generation. 18 | 19 | This exception is principally used in contrib.openstack.context 20 | """ 21 | pass 22 | 23 | 24 | class ServiceActionError(Exception): 25 | """Raised when a service action (stop/start/ etc) failed.""" 26 | pass 27 | -------------------------------------------------------------------------------- /templates/ocata/neutron.conf: -------------------------------------------------------------------------------- 1 | # mitaka 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | verbose = {{ verbose }} 8 | debug = {{ debug }} 9 | core_plugin = {{ core_plugin }} 10 | {% if network_device_mtu -%} 11 | network_device_mtu = {{ network_device_mtu }} 12 | {% endif -%} 13 | api_workers = {{ workers }} 14 | rpc_response_timeout = {{ rpc_response_timeout }} 15 | {% if transport_url %} 16 | transport_url = {{ transport_url }} 17 | {% endif %} 18 | 19 | [agent] 20 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 21 | report_interval = {{ report_interval }} 22 | {% include "parts/agent" %} 23 | 24 | {% include "section-oslo-messaging-rabbit-ocata" %} 25 | 26 | {% include "section-oslo-notifications" %} 27 | 28 | [oslo_concurrency] 29 | lock_path = /var/lock/neutron 30 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # This file is managed centrally by release-tools and should not be modified 2 | # within individual charm repos. See the 'global' dir contents for available 3 | # choices of *requirements.txt files for OpenStack Charms: 4 | # https://github.com/openstack-charmers/release-tools 5 | # 6 | # TODO: Distill the func test requirements from the lint/unit test 7 | # requirements. They are intertwined. Also, Zaza itself should specify 8 | # all of its own requirements and if it doesn't, fix it there. 9 | # 10 | pbr==5.6.0 11 | simplejson>=2.2.0 12 | netifaces>=0.10.4 13 | 14 | # NOTE: newer versions of cryptography require a Rust compiler to build, 15 | # see 16 | # * https://github.com/openstack-charmers/zaza/issues/421 17 | # * https://mail.python.org/pipermail/cryptography-dev/2021-January/001003.html 18 | # 19 | cryptography<3.4 20 | 21 | # Strange import error with newer netaddr: 22 | netaddr>0.7.16,<0.8.0 23 | 24 | Jinja2>=2.6 # BSD License (3 clause) 25 | six>=1.9.0 26 | 27 | dnspython 28 | 29 | psutil>=1.1.1,<2.0.0 30 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/apache/templates/99-hardening.conf: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # WARNING: This configuration file is maintained by Juju. Local changes may 3 | # be overwritten. 4 | ############################################################################### 5 | 6 | 7 | 8 | # http://httpd.apache.org/docs/2.4/upgrading.html 9 | {% if apache_version > '2.2' -%} 10 | Require all granted 11 | {% else -%} 12 | Order Allow,Deny 13 | Deny from all 14 | {% endif %} 15 | 16 | 17 | 18 | 19 | Options -Indexes -FollowSymLinks 20 | AllowOverride None 21 | 22 | 23 | 24 | Options -Indexes -FollowSymLinks 25 | AllowOverride None 26 | 27 | 28 | TraceEnable {{ traceenable }} 29 | ServerTokens {{ servertokens }} 30 | 31 | SSLHonorCipherOrder {{ honor_cipher_order }} 32 | SSLCipherSuite {{ cipher_suite }} 33 | -------------------------------------------------------------------------------- /templates/icehouse/dhcp_agent.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [DEFAULT] 6 | state_path = /var/lib/neutron 7 | interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver 8 | dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq 9 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 10 | debug = {{ debug }} 11 | 12 | {% if instance_mtu or dnsmasq_flags -%} 13 | dnsmasq_config_file = /etc/neutron/dnsmasq.conf 14 | {% endif -%} 15 | {% if plugin == 'nvp' or plugin == 'nsx' -%} 16 | enable_metadata_network = True 17 | enable_isolated_metadata = True 18 | {% endif -%} 19 | 20 | {% if plugin == 'n1kv' %} 21 | enable_metadata_network = True 22 | enable_isolated_metadata = True 23 | resync_interval = 30 24 | use_namespaces = True 25 | dhcp_lease_time=3600 26 | {% else %} 27 | ovs_use_veth = {{ ovs_use_veth }} 28 | {% endif %} 29 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/defaults/ssh.yaml.schema: -------------------------------------------------------------------------------- 1 | # NOTE: this schema must contain all valid keys from it's associated defaults 2 | # file. It is used to validate user-provided overrides. 3 | common: 4 | service_name: 5 | network_ipv6_enable: 6 | ports: 7 | remote_hosts: 8 | client: 9 | package: 10 | cbc_required: 11 | weak_hmac: 12 | weak_kex: 13 | roaming: 14 | password_authentication: 15 | server: 16 | host_key_files: 17 | cbc_required: 18 | weak_hmac: 19 | weak_kex: 20 | allow_root_with_key: 21 | allow_tcp_forwarding: 22 | allow_agent_forwarding: 23 | allow_x11_forwarding: 24 | use_privilege_separation: 25 | listen_to: 26 | use_pam: 27 | package: 28 | password_authentication: 29 | alive_interval: 30 | alive_count: 31 | sftp_enable: 32 | sftp_group: 33 | sftp_chroot: 34 | deny_users: 35 | allow_users: 36 | deny_groups: 37 | allow_groups: 38 | print_motd: 39 | print_last_log: 40 | use_dns: 41 | max_auth_tries: 42 | max_sessions: 43 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/network/ovs/utils.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Canonical Ltd 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | import subprocess 15 | 16 | 17 | def _run(*args): 18 | """Run a process, check result, capture decoded output from STDOUT. 19 | 20 | :param args: Command and arguments to run 21 | :type args: Tuple[str, ...] 22 | :returns: Information about the completed process 23 | :rtype: str 24 | :raises subprocess.CalledProcessError 25 | """ 26 | return subprocess.check_output(args, universal_newlines=True) 27 | -------------------------------------------------------------------------------- /templates/icehouse/ml2_conf.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [ml2] 6 | type_drivers = gre,vxlan,vlan,flat 7 | tenant_network_types = gre,vxlan,vlan,flat 8 | mechanism_drivers = openvswitch,hyperv,l2population 9 | 10 | [ml2_type_gre] 11 | tunnel_id_ranges = 1:1000 12 | 13 | [ml2_type_vxlan] 14 | vni_ranges = 1001:2000 15 | 16 | [ml2_type_vlan] 17 | network_vlan_ranges = {{ vlan_ranges }} 18 | 19 | [ml2_type_flat] 20 | flat_networks = {{ network_providers }} 21 | 22 | [ovs] 23 | enable_tunneling = True 24 | local_ip = {{ local_ip }} 25 | bridge_mappings = {{ bridge_mappings }} 26 | 27 | [agent] 28 | tunnel_types = {{ overlay_network_type }} 29 | l2_population = {{ l2_population }} 30 | {% if veth_mtu -%} 31 | veth_mtu = {{ veth_mtu }} 32 | {% endif %} 33 | 34 | [securitygroup] 35 | firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver 36 | -------------------------------------------------------------------------------- /templates/icehouse/metadata_agent.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | # Metadata service seems to cache neutron api url from keystone so trigger 6 | # restart if it changes: {{ quantum_url }} 7 | [DEFAULT] 8 | auth_url = {{ auth_protocol }}://{{ keystone_host }}:{{ auth_port }}/v2.0 9 | auth_region = {{ region }} 10 | admin_tenant_name = {{ service_tenant }} 11 | admin_user = {{ service_username }} 12 | admin_password = {{ service_password }} 13 | root_helper = sudo neutron-rootwrap /etc/neutron/rootwrap.conf 14 | state_path = /var/lib/neutron 15 | # Gateway runs a metadata API server locally 16 | nova_metadata_ip = {{ nova_metadata_host }} 17 | nova_metadata_port = {{ nova_metadata_port }} 18 | nova_metadata_protocol = {{ nova_metadata_protocol }} 19 | metadata_proxy_shared_secret = {{ shared_secret }} 20 | cache_url = memory://?default_ttl=5 21 | metadata_workers = {{ workers }} 22 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-keystone-authtoken-mitaka: -------------------------------------------------------------------------------- 1 | {% if auth_host -%} 2 | [keystone_authtoken] 3 | auth_type = password 4 | {% if api_version == "3" -%} 5 | auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/v3 6 | auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v3 7 | project_domain_name = {{ admin_domain_name }} 8 | user_domain_name = {{ admin_domain_name }} 9 | {% if service_type -%} 10 | service_type = {{ service_type }} 11 | {% endif -%} 12 | {% else -%} 13 | auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }} 14 | auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }} 15 | project_domain_name = default 16 | user_domain_name = default 17 | {% endif -%} 18 | project_name = {{ admin_tenant_name }} 19 | username = {{ admin_user }} 20 | password = {{ admin_password }} 21 | signing_dir = {{ signing_dir }} 22 | {% if use_memcache == true %} 23 | memcached_servers = {{ memcache_url }} 24 | {% endif -%} 25 | {% if admin_role -%} 26 | service_token_roles = {{ admin_role }} 27 | service_token_roles_required = True 28 | {% endif -%} 29 | {% endif -%} 30 | -------------------------------------------------------------------------------- /templates/juno/ml2_conf.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [ml2] 6 | type_drivers = gre,vxlan,vlan,flat 7 | tenant_network_types = gre,vxlan,vlan,flat 8 | mechanism_drivers = openvswitch,hyperv,l2population 9 | 10 | [ml2_type_gre] 11 | tunnel_id_ranges = 1:1000 12 | 13 | [ml2_type_vxlan] 14 | vni_ranges = 1001:2000 15 | 16 | [ml2_type_vlan] 17 | network_vlan_ranges = {{ vlan_ranges }} 18 | 19 | [ml2_type_flat] 20 | flat_networks = {{ network_providers }} 21 | 22 | [ovs] 23 | enable_tunneling = True 24 | local_ip = {{ local_ip }} 25 | bridge_mappings = {{ bridge_mappings }} 26 | 27 | [agent] 28 | tunnel_types = {{ overlay_network_type }} 29 | l2_population = {{ l2_population }} 30 | enable_distributed_routing = {{ enable_dvr }} 31 | {% if veth_mtu -%} 32 | veth_mtu = {{ veth_mtu }} 33 | {% endif %} 34 | 35 | [securitygroup] 36 | firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver 37 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/defaults/os.yaml.schema: -------------------------------------------------------------------------------- 1 | # NOTE: this schema must contain all valid keys from it's associated defaults 2 | # file. It is used to validate user-provided overrides. 3 | general: 4 | desktop_enable: 5 | environment: 6 | extra_user_paths: 7 | umask: 8 | root_path: 9 | auth: 10 | pw_max_age: 11 | pw_min_age: 12 | retries: 13 | lockout_time: 14 | timeout: 15 | allow_homeless: 16 | pam_passwdqc_enable: 17 | pam_passwdqc_options: 18 | root_ttys: 19 | uid_min: 20 | gid_min: 21 | sys_uid_min: 22 | sys_uid_max: 23 | sys_gid_min: 24 | sys_gid_max: 25 | chfn_restrict: 26 | security: 27 | users_allow: 28 | suid_sgid_enforce: 29 | suid_sgid_blacklist: 30 | suid_sgid_whitelist: 31 | suid_sgid_dry_run_on_unknown: 32 | suid_sgid_remove_from_unknown: 33 | packages_clean: 34 | packages_list: 35 | kernel_enable_module_loading: 36 | kernel_enable_core_dump: 37 | ssh_tmout: 38 | sysctl: 39 | kernel_secure_sysrq: 40 | kernel_enable_sysrq: 41 | forwarding: 42 | ipv6_enable: 43 | arp_restricted: 44 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/files/check_haproxy_queue_depth.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #-------------------------------------------- 3 | # This file is managed by Juju 4 | #-------------------------------------------- 5 | # 6 | # Copyright 2009,2012 Canonical Ltd. 7 | # Author: Tom Haddon 8 | 9 | # These should be config options at some stage 10 | CURRQthrsh=0 11 | MAXQthrsh=100 12 | 13 | AUTH=$(grep -r "stats auth" /etc/haproxy/haproxy.cfg | awk 'NR=1{print $3}') 14 | 15 | HAPROXYSTATS=$(/usr/lib/nagios/plugins/check_http -a ${AUTH} -I 127.0.0.1 -p 8888 -u '/;csv' -v) 16 | 17 | for BACKEND in $(echo $HAPROXYSTATS| xargs -n1 | grep BACKEND | awk -F , '{print $1}') 18 | do 19 | CURRQ=$(echo "$HAPROXYSTATS" | grep $BACKEND | grep BACKEND | cut -d , -f 3) 20 | MAXQ=$(echo "$HAPROXYSTATS" | grep $BACKEND | grep BACKEND | cut -d , -f 4) 21 | 22 | if [[ $CURRQ -gt $CURRQthrsh || $MAXQ -gt $MAXQthrsh ]] ; then 23 | echo "CRITICAL: queue depth for $BACKEND - CURRENT:$CURRQ MAX:$MAXQ" 24 | exit 2 25 | fi 26 | done 27 | 28 | echo "OK: All haproxy queue depths looking good" 29 | exit 0 30 | 31 | -------------------------------------------------------------------------------- /hooks/charmhelpers/cli/host.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from . import cmdline 16 | from charmhelpers.core import host 17 | 18 | 19 | @cmdline.subcommand() 20 | def mounts(): 21 | "List mounts" 22 | return host.mounts() 23 | 24 | 25 | @cmdline.subcommand_builder('service', description="Control system services") 26 | def service(subparser): 27 | subparser.add_argument("action", help="The action to perform (start, stop, etc...)") 28 | subparser.add_argument("service_name", help="Name of the service to control") 29 | return host.service 30 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/ssh/checks/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from charmhelpers.core.hookenv import ( 16 | log, 17 | DEBUG, 18 | ) 19 | from charmhelpers.contrib.hardening.ssh.checks import config 20 | 21 | 22 | def run_ssh_checks(): 23 | log("Starting SSH hardening checks.", level=DEBUG) 24 | checks = config.get_audits() 25 | for check in checks: 26 | log("Running '%s' check" % (check.__class__.__name__), level=DEBUG) 27 | check.ensure_compliance() 28 | 29 | log("SSH hardening checks complete.", level=DEBUG) 30 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/mysql/checks/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from charmhelpers.core.hookenv import ( 16 | log, 17 | DEBUG, 18 | ) 19 | from charmhelpers.contrib.hardening.mysql.checks import config 20 | 21 | 22 | def run_mysql_checks(): 23 | log("Starting MySQL hardening checks.", level=DEBUG) 24 | checks = config.get_audits() 25 | for check in checks: 26 | log("Running '%s' check" % (check.__class__.__name__), level=DEBUG) 27 | check.ensure_compliance() 28 | 29 | log("MySQL hardening checks complete.", level=DEBUG) 30 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/apache/checks/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from charmhelpers.core.hookenv import ( 16 | log, 17 | DEBUG, 18 | ) 19 | from charmhelpers.contrib.hardening.apache.checks import config 20 | 21 | 22 | def run_apache_checks(): 23 | log("Starting Apache hardening checks.", level=DEBUG) 24 | checks = config.get_audits() 25 | for check in checks: 26 | log("Running '%s' check" % (check.__class__.__name__), level=DEBUG) 27 | check.ensure_compliance() 28 | 29 | log("Apache hardening checks complete.", level=DEBUG) 30 | -------------------------------------------------------------------------------- /templates/mitaka/l3_agent.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [DEFAULT] 6 | interface_driver = openvswitch 7 | auth_url = {{ auth_protocol }}://{{ keystone_host }}:{{ auth_port }}/v2.0 8 | auth_region = {{ region }} 9 | admin_tenant_name = {{ service_tenant }} 10 | admin_user = {{ service_username }} 11 | admin_password = {{ service_password }} 12 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 13 | handle_internal_only_routers = {{ handle_internal_only_router }} 14 | {% if plugin == 'n1kv' %} 15 | l3_agent_manager = neutron.agent.l3_agent.L3NATAgentWithStateReport 16 | external_network_bridge = br-int 17 | ovs_use_veth = False 18 | use_namespaces = True 19 | {% else %} 20 | ovs_use_veth = True 21 | {% endif %} 22 | {% if external_configuration_new -%} 23 | gateway_external_network_id = 24 | external_network_bridge = 25 | {% elif ext_net_id %} 26 | gateway_external_network_id = {{ ext_net_id }} 27 | {% endif -%} 28 | agent_mode = {{ agent_mode }} 29 | -------------------------------------------------------------------------------- /templates/icehouse/l3_agent.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [DEFAULT] 6 | interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver 7 | auth_url = {{ auth_protocol }}://{{ keystone_host }}:{{ auth_port }}/v2.0 8 | auth_region = {{ region }} 9 | admin_tenant_name = {{ service_tenant }} 10 | admin_user = {{ service_username }} 11 | admin_password = {{ service_password }} 12 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 13 | handle_internal_only_routers = {{ handle_internal_only_router }} 14 | {% if plugin == 'n1kv' %} 15 | l3_agent_manager = neutron.agent.l3_agent.L3NATAgentWithStateReport 16 | external_network_bridge = br-int 17 | ovs_use_veth = False 18 | use_namespaces = True 19 | {% else %} 20 | ovs_use_veth = True 21 | {% endif %} 22 | {% if external_configuration_new -%} 23 | gateway_external_network_id = 24 | external_network_bridge = 25 | {% elif ext_net_id %} 26 | gateway_external_network_id = {{ ext_net_id }} 27 | {% endif -%} 28 | -------------------------------------------------------------------------------- /templates/kilo/nova.conf: -------------------------------------------------------------------------------- 1 | # kilo 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | logdir=/var/log/nova 8 | state_path=/var/lib/nova 9 | root_helper=sudo nova-rootwrap /etc/nova/rootwrap.conf 10 | debug = {{ debug }} 11 | verbose= {{ verbose }} 12 | use_syslog = {{ use_syslog }} 13 | api_paste_config=/etc/nova/api-paste.ini 14 | enabled_apis=metadata 15 | multi_host=True 16 | # Access to neutron API services 17 | network_api_class=nova.network.neutronv2.api.API 18 | metadata_workers = {{ workers }} 19 | 20 | [neutron] 21 | auth_strategy=keystone 22 | url={{ quantum_url }} 23 | admin_tenant_name={{ service_tenant }} 24 | admin_username={{ service_username }} 25 | admin_password={{ service_password }} 26 | admin_auth_url={{ auth_protocol }}://{{ keystone_host }}:{{ auth_port }}/v2.0 27 | service_metadata_proxy=True 28 | metadata_proxy_shared_secret={{ shared_secret }} 29 | 30 | {% include "section-rabbitmq-oslo" %} 31 | 32 | [oslo_concurrency] 33 | lock_path=/var/lock/nova 34 | -------------------------------------------------------------------------------- /templates/icehouse/nova.conf: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [DEFAULT] 6 | logdir=/var/log/nova 7 | state_path=/var/lib/nova 8 | lock_path=/var/lock/nova 9 | root_helper=sudo nova-rootwrap /etc/nova/rootwrap.conf 10 | debug = {{ debug }} 11 | verbose= {{ verbose }} 12 | use_syslog = {{ use_syslog }} 13 | api_paste_config=/etc/nova/api-paste.ini 14 | enabled_apis=metadata 15 | multi_host=True 16 | neutron_metadata_proxy_shared_secret={{ shared_secret }} 17 | service_neutron_metadata_proxy=True 18 | metadata_workers = {{ workers }} 19 | # Access to message bus 20 | {% include "parts/rabbitmq" %} 21 | # Access to neutron API services 22 | network_api_class=nova.network.neutronv2.api.API 23 | neutron_auth_strategy=keystone 24 | neutron_url={{ quantum_url }} 25 | neutron_admin_tenant_name={{ service_tenant }} 26 | neutron_admin_username={{ service_username }} 27 | neutron_admin_password={{ service_password }} 28 | neutron_admin_auth_url={{ auth_protocol }}://{{ keystone_host }}:{{ auth_port }}/v2.0 29 | -------------------------------------------------------------------------------- /hooks/charmhelpers/fetch/python/version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # Copyright 2014-2015 Canonical Limited. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | import sys 19 | 20 | __author__ = "Jorge Niedbalski " 21 | 22 | 23 | def current_version(): 24 | """Current system python version""" 25 | return sys.version_info 26 | 27 | 28 | def current_version_string(): 29 | """Current system python version as string major.minor.micro""" 30 | return "{0}.{1}.{2}".format(sys.version_info.major, 31 | sys.version_info.minor, 32 | sys.version_info.micro) 33 | -------------------------------------------------------------------------------- /templates/juno/l3_agent.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [DEFAULT] 6 | interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver 7 | auth_url = {{ auth_protocol }}://{{ keystone_host }}:{{ auth_port }}/v2.0 8 | auth_region = {{ region }} 9 | admin_tenant_name = {{ service_tenant }} 10 | admin_user = {{ service_username }} 11 | admin_password = {{ service_password }} 12 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 13 | handle_internal_only_routers = {{ handle_internal_only_router }} 14 | {% if plugin == 'n1kv' %} 15 | l3_agent_manager = neutron.agent.l3_agent.L3NATAgentWithStateReport 16 | external_network_bridge = br-int 17 | ovs_use_veth = False 18 | use_namespaces = True 19 | {% else %} 20 | ovs_use_veth = True 21 | {% endif %} 22 | {% if external_configuration_new -%} 23 | gateway_external_network_id = 24 | external_network_bridge = 25 | {% elif ext_net_id %} 26 | gateway_external_network_id = {{ ext_net_id }} 27 | {% endif -%} 28 | agent_mode = {{ agent_mode }} 29 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/files/check_haproxy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #-------------------------------------------- 3 | # This file is managed by Juju 4 | #-------------------------------------------- 5 | # 6 | # Copyright 2009,2012 Canonical Ltd. 7 | # Author: Tom Haddon 8 | 9 | CRITICAL=0 10 | NOTACTIVE='' 11 | LOGFILE=/var/log/nagios/check_haproxy.log 12 | AUTH=$(grep -r "stats auth" /etc/haproxy/haproxy.cfg | awk 'NR=1{print $3}') 13 | 14 | typeset -i N_INSTANCES=0 15 | for appserver in $(awk '/^\s+server/{print $2}' /etc/haproxy/haproxy.cfg) 16 | do 17 | N_INSTANCES=N_INSTANCES+1 18 | output=$(/usr/lib/nagios/plugins/check_http -a ${AUTH} -I 127.0.0.1 -p 8888 -u '/;csv' --regex=",${appserver},.*,UP.*" -e ' 200 OK') 19 | if [ $? != 0 ]; then 20 | date >> $LOGFILE 21 | echo $output >> $LOGFILE 22 | /usr/lib/nagios/plugins/check_http -a ${AUTH} -I 127.0.0.1 -p 8888 -u '/;csv' -v | grep ",${appserver}," >> $LOGFILE 2>&1 23 | CRITICAL=1 24 | NOTACTIVE="${NOTACTIVE} $appserver" 25 | fi 26 | done 27 | 28 | if [ $CRITICAL = 1 ]; then 29 | echo "CRITICAL:${NOTACTIVE}" 30 | exit 2 31 | fi 32 | 33 | echo "OK: All haproxy instances ($N_INSTANCES) looking good" 34 | exit 0 35 | -------------------------------------------------------------------------------- /hooks/charmhelpers/cli/commands.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """ 16 | This module loads sub-modules into the python runtime so they can be 17 | discovered via the inspect module. In order to prevent flake8 from (rightfully) 18 | telling us these are unused modules, throw a ' # noqa' at the end of each import 19 | so that the warning is suppressed. 20 | """ 21 | 22 | from . import CommandLine # noqa 23 | 24 | """ 25 | Import the sub-modules which have decorated subcommands to register with chlp. 26 | """ 27 | from . import host # noqa 28 | from . import benchmark # noqa 29 | from . import unitdata # noqa 30 | from . import hookenv # noqa 31 | -------------------------------------------------------------------------------- /templates/queens/l3_agent.ini: -------------------------------------------------------------------------------- 1 | # newton 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | interface_driver = openvswitch 8 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 9 | handle_internal_only_routers = {{ handle_internal_only_router }} 10 | {% if plugin == 'n1kv' %} 11 | l3_agent_manager = neutron.agent.l3_agent.L3NATAgentWithStateReport 12 | external_network_bridge = br-int 13 | ovs_use_veth = False 14 | use_namespaces = True 15 | {% else %} 16 | ovs_use_veth = True 17 | {% endif %} 18 | {% if external_configuration_new -%} 19 | gateway_external_network_id = 20 | external_network_bridge = 21 | {% elif ext_net_id %} 22 | gateway_external_network_id = {{ ext_net_id }} 23 | {% else %} 24 | # Set default to deprecated external networking config 25 | external_network_bridge = br-ex 26 | {% endif -%} 27 | agent_mode = {{ agent_mode }} 28 | {% if use_l3ha and keepalived_healthcheck_interval -%} 29 | ha_vrrp_health_check_interval = {{ keepalived_healthcheck_interval }} 30 | {% endif -%} 31 | 32 | [AGENT] 33 | extensions = fwaas 34 | -------------------------------------------------------------------------------- /actions/openstack_upgrade.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import sys 4 | 5 | _path = os.path.dirname(os.path.realpath(__file__)) 6 | _hooks_dir = os.path.abspath(os.path.join(_path, "..", "hooks")) 7 | 8 | 9 | def _add_path(path): 10 | if path not in sys.path: 11 | sys.path.insert(1, path) 12 | 13 | 14 | _add_path(_hooks_dir) 15 | 16 | 17 | from charmhelpers.contrib.openstack.utils import ( 18 | do_action_openstack_upgrade, 19 | ) 20 | 21 | from neutron_utils import ( 22 | do_openstack_upgrade, 23 | NEUTRON_COMMON, 24 | ) 25 | 26 | from neutron_hooks import ( 27 | config_changed, 28 | resolve_CONFIGS, 29 | ) 30 | 31 | 32 | def openstack_upgrade(): 33 | """Upgrade packages to config-set Openstack version. 34 | 35 | If the charm was installed from source we cannot upgrade it. 36 | For backwards compatibility a config flag must be set for this 37 | code to run, otherwise a full service level upgrade will fire 38 | on config-changed.""" 39 | 40 | if do_action_openstack_upgrade(NEUTRON_COMMON, 41 | do_openstack_upgrade, 42 | resolve_CONFIGS()): 43 | config_changed() 44 | 45 | 46 | if __name__ == '__main__': 47 | openstack_upgrade() 48 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/README.hardening.md: -------------------------------------------------------------------------------- 1 | # Juju charm-helpers hardening library 2 | 3 | ## Description 4 | 5 | This library provides multiple implementations of system and application 6 | hardening that conform to the standards of http://hardening.io/. 7 | 8 | Current implementations include: 9 | 10 | * OS 11 | * SSH 12 | * MySQL 13 | * Apache 14 | 15 | ## Requirements 16 | 17 | * Juju Charms 18 | 19 | ## Usage 20 | 21 | 1. Synchronise this library into your charm and add the harden() decorator 22 | (from contrib.hardening.harden) to any functions or methods you want to use 23 | to trigger hardening of your application/system. 24 | 25 | 2. Add a config option called 'harden' to your charm config.yaml and set it to 26 | a space-delimited list of hardening modules you want to run e.g. "os ssh" 27 | 28 | 3. Override any config defaults (contrib.hardening.defaults) by adding a file 29 | called hardening.yaml to your charm root containing the name(s) of the 30 | modules whose settings you want override at root level and then any settings 31 | with overrides e.g. 32 | 33 | os: 34 | general: 35 | desktop_enable: True 36 | 37 | 4. Now just run your charm as usual and hardening will be applied each time the 38 | hook runs. 39 | -------------------------------------------------------------------------------- /templates/rocky/l3_agent.ini: -------------------------------------------------------------------------------- 1 | # newton 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | interface_driver = openvswitch 8 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 9 | handle_internal_only_routers = {{ handle_internal_only_router }} 10 | {% if plugin == 'n1kv' %} 11 | l3_agent_manager = neutron.agent.l3_agent.L3NATAgentWithStateReport 12 | external_network_bridge = br-int 13 | ovs_use_veth = False 14 | use_namespaces = True 15 | {% else %} 16 | ovs_use_veth = True 17 | {% endif %} 18 | {% if external_configuration_new -%} 19 | gateway_external_network_id = 20 | external_network_bridge = 21 | {% elif ext_net_id %} 22 | gateway_external_network_id = {{ ext_net_id }} 23 | {% else %} 24 | # Set default to deprecated external networking config 25 | external_network_bridge = br-ex 26 | {% endif -%} 27 | agent_mode = {{ agent_mode }} 28 | {% if use_l3ha and keepalived_healthcheck_interval -%} 29 | ha_vrrp_health_check_interval = {{ keepalived_healthcheck_interval }} 30 | {% endif -%} 31 | 32 | [AGENT] 33 | extensions = {{ l3_extension_plugins }} 34 | -------------------------------------------------------------------------------- /test-requirements.txt: -------------------------------------------------------------------------------- 1 | # This file is managed centrally by release-tools and should not be modified 2 | # within individual charm repos. See the 'global' dir contents for available 3 | # choices of *requirements.txt files for OpenStack Charms: 4 | # https://github.com/openstack-charmers/release-tools 5 | # 6 | # TODO: Distill the func test requirements from the lint/unit test 7 | # requirements. They are intertwined. Also, Zaza itself should specify 8 | # all of its own requirements and if it doesn't, fix it there. 9 | # 10 | pyparsing<3.0.0 # aodhclient is pinned in zaza and needs pyparsing < 3.0.0, but cffi also needs it, so pin here. 11 | 12 | requests>=2.18.4 13 | 14 | stestr>=2.2.0 15 | 16 | # Dependency of stestr. Workaround for 17 | # https://github.com/mtreinish/stestr/issues/145 18 | cliff<3.0.0 19 | 20 | coverage>=4.5.2 21 | pyudev # for ceph-* charm unit tests (need to fix the ceph-* charm unit tests/mocking) 22 | git+https://github.com/openstack-charmers/zaza.git#egg=zaza 23 | git+https://github.com/openstack-charmers/zaza-openstack-tests.git#egg=zaza.openstack 24 | 25 | # Needed for charm-glance: 26 | git+https://opendev.org/openstack/tempest.git#egg=tempest 27 | 28 | croniter # needed for charm-rabbitmq-server unit tests 29 | psutil 30 | -------------------------------------------------------------------------------- /templates/mitaka/dhcp_agent.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [DEFAULT] 6 | state_path = /var/lib/neutron 7 | interface_driver = openvswitch 8 | dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq 9 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 10 | debug = {{ debug }} 11 | 12 | {% if instance_mtu or dnsmasq_flags -%} 13 | dnsmasq_config_file = /etc/neutron/dnsmasq.conf 14 | {% endif -%} 15 | 16 | {% if dns_servers -%} 17 | dnsmasq_dns_servers = {{ dns_servers }} 18 | {% endif -%} 19 | 20 | {% if dns_domain -%} 21 | dns_domain = {{ dns_domain }} 22 | # Per LP#1583769, dhcp_domain needs to be configured as well. Additional 23 | # testing shows that this has not been changed in newton, so will also 24 | # specify the dhcp_domain field. 25 | dhcp_domain = {{ dns_domain }} 26 | {% endif -%} 27 | 28 | enable_metadata_network = {{ enable_metadata_network }} 29 | enable_isolated_metadata = {{ enable_isolated_metadata }} 30 | 31 | {% if plugin == 'n1kv' %} 32 | resync_interval = 30 33 | use_namespaces = True 34 | dhcp_lease_time=3600 35 | {% else %} 36 | ovs_use_veth = {{ ovs_use_veth }} 37 | {% endif %} 38 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/apache/templates/alias.conf: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # WARNING: This configuration file is maintained by Juju. Local changes may 3 | # be overwritten. 4 | ############################################################################### 5 | 6 | # 7 | # Aliases: Add here as many aliases as you need (with no limit). The format is 8 | # Alias fakename realname 9 | # 10 | # Note that if you include a trailing / on fakename then the server will 11 | # require it to be present in the URL. So "/icons" isn't aliased in this 12 | # example, only "/icons/". If the fakename is slash-terminated, then the 13 | # realname must also be slash terminated, and if the fakename omits the 14 | # trailing slash, the realname must also omit it. 15 | # 16 | # We include the /icons/ alias for FancyIndexed directory listings. If 17 | # you do not use FancyIndexing, you may comment this out. 18 | # 19 | Alias /icons/ "{{ apache_icondir }}/" 20 | 21 | 22 | Options -Indexes -MultiViews -FollowSymLinks 23 | AllowOverride None 24 | {% if apache_version == '2.4' -%} 25 | Require all granted 26 | {% else -%} 27 | Order allow,deny 28 | Allow from all 29 | {% endif %} 30 | 31 | 32 | -------------------------------------------------------------------------------- /templates/ocata/dhcp_agent.ini: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # Configuration file maintained by Juju. Local changes may be overwritten. 4 | ############################################################################### 5 | [DEFAULT] 6 | state_path = /var/lib/neutron 7 | interface_driver = openvswitch 8 | dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq 9 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 10 | debug = {{ debug }} 11 | 12 | {% if instance_mtu or dnsmasq_flags -%} 13 | dnsmasq_config_file = /etc/neutron/dnsmasq.conf 14 | {% endif -%} 15 | 16 | {% if dns_servers -%} 17 | dnsmasq_dns_servers = {{ dns_servers }} 18 | {% endif -%} 19 | 20 | {% if dns_domain -%} 21 | dns_domain = {{ dns_domain }} 22 | # Per LP#1583769, dhcp_domain needs to be configured as well. Additional 23 | # testing shows that this has not been changed in newton, so will also 24 | # specify the dhcp_domain field. 25 | dhcp_domain = {{ dns_domain }} 26 | {% endif -%} 27 | 28 | enable_metadata_network = {{ enable_metadata_network }} 29 | {% if enable_isolated_metadata -%} 30 | enable_isolated_metadata = True 31 | force_metadata = True 32 | {% endif -%} 33 | 34 | {% if plugin == 'n1kv' %} 35 | resync_interval = 30 36 | use_namespaces = True 37 | dhcp_lease_time=3600 38 | {% else %} 39 | ovs_use_veth = {{ ovs_use_veth }} 40 | {% endif %} 41 | -------------------------------------------------------------------------------- /templates/usr.bin.neutron-lbaas-agent: -------------------------------------------------------------------------------- 1 | # Last Modified: Fri Apr 1 16:26:34 2016 2 | # Mode: {{aa_profile_mode}} 3 | #include 4 | 5 | /usr/bin/neutron-lbaas-agent { 6 | #include 7 | #include 8 | #include 9 | 10 | /usr/bin/neutron-lbaas-agent r, 11 | 12 | /sbin/ldconfig* rix, 13 | 14 | /bin/ r, 15 | /bin/** rix, 16 | /usr/bin/ r, 17 | /usr/bin/** rix, 18 | 19 | /etc/neutron/** r, 20 | /var/lib/neutron/** rwk, 21 | /var/log/neutron/** rwk, 22 | /{,var/}run/neutron/** rwk, 23 | /{,var/}run/lock/neutron/** rwk, 24 | 25 | # Allow unconfined sudo to support oslo.rootwrap 26 | # profile makes no attempt to restrict this as this 27 | # is limited by the appropriate rootwrap configuration. 28 | /usr/bin/sudo Ux, 29 | 30 | # Allow ip to run unrestricted for unpriviledged commands 31 | /{,s}bin/ip Ux, 32 | 33 | /tmp/* rw, 34 | /var/tmp/* a, 35 | 36 | # Required for parsing of managed process cmdline arguments 37 | /proc/*/cmdline r, 38 | 39 | # Required for assessment of current state of networking 40 | /proc/sys/net/** r, 41 | 42 | {% if ubuntu_release <= '12.04' %} 43 | /proc/*/mounts r, 44 | /proc/*/status r, 45 | /proc/*/ns/net r, 46 | {% else %} 47 | owner @{PROC}/@{pid}/mounts r, 48 | owner @{PROC}/@{pid}/status r, 49 | owner @{PROC}/@{pid}/ns/net r, 50 | {% endif %} 51 | } 52 | -------------------------------------------------------------------------------- /metadata.yaml: -------------------------------------------------------------------------------- 1 | name: neutron-gateway 2 | summary: OpenStack Networking - Neutron Gateway 3 | maintainer: OpenStack Charmers 4 | description: | 5 | Neutron is a virtual network service for Openstack, and a part of 6 | Netstack. Just like OpenStack Nova provides an API to dynamically 7 | request and configure virtual servers, Neutron provides an API to 8 | dynamically request and configure virtual networks. These networks 9 | connect "interfaces" from other OpenStack services (e.g., virtual NICs 10 | from Nova VMs). The Neutron API supports extensions to provide 11 | advanced network capabilities (e.g., QoS, ACLs, network monitoring, 12 | etc.) 13 | . 14 | This charm provides central Neutron networking services as part 15 | of a Neutron based OpenStack deployment 16 | docs: https://discourse.charmhub.io/t/neutron-gateway-docs-index/11000 17 | tags: 18 | - openstack 19 | series: 20 | - jammy 21 | extra-bindings: 22 | data: 23 | provides: 24 | nrpe-external-master: 25 | interface: nrpe-external-master 26 | scope: container 27 | quantum-network-service: 28 | interface: quantum 29 | requires: 30 | amqp: 31 | interface: rabbitmq 32 | amqp-nova: 33 | interface: rabbitmq 34 | neutron-plugin-api: 35 | interface: neutron-plugin-api 36 | ha: 37 | interface: hacluster 38 | scope: container 39 | peers: 40 | cluster: 41 | interface: quantum-gateway-ha 42 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/checks/apt.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from charmhelpers.contrib.hardening.utils import get_settings 16 | from charmhelpers.contrib.hardening.audits.apt import ( 17 | AptConfig, 18 | RestrictedPackages, 19 | ) 20 | 21 | 22 | def get_audits(): 23 | """Get OS hardening apt audits. 24 | 25 | :returns: dictionary of audits 26 | """ 27 | audits = [AptConfig([{'key': 'APT::Get::AllowUnauthenticated', 28 | 'expected': 'false'}])] 29 | 30 | settings = get_settings('os') 31 | clean_packages = settings['security']['packages_clean'] 32 | if clean_packages: 33 | security_packages = settings['security']['packages_list'] 34 | if security_packages: 35 | audits.append(RestrictedPackages(security_packages)) 36 | 37 | return audits 38 | -------------------------------------------------------------------------------- /hooks/charmhelpers/cli/benchmark.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from . import cmdline 16 | from charmhelpers.contrib.benchmark import Benchmark 17 | 18 | 19 | @cmdline.subcommand(command_name='benchmark-start') 20 | def start(): 21 | Benchmark.start() 22 | 23 | 24 | @cmdline.subcommand(command_name='benchmark-finish') 25 | def finish(): 26 | Benchmark.finish() 27 | 28 | 29 | @cmdline.subcommand_builder('benchmark-composite', description="Set the benchmark composite score") 30 | def service(subparser): 31 | subparser.add_argument("value", help="The composite score.") 32 | subparser.add_argument("units", help="The units the composite score represents, i.e., 'reads/sec'.") 33 | subparser.add_argument("direction", help="'asc' if a lower score is better, 'desc' if a higher score is better.") 34 | return Benchmark.set_composite_score 35 | -------------------------------------------------------------------------------- /templates/usr.bin.nova-api-metadata: -------------------------------------------------------------------------------- 1 | # Last Modified: Fri Apr 1 16:26:34 2016 2 | # Mode: {{aa_profile_mode}} 3 | #include 4 | 5 | /usr/bin/nova-metadata-api { 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /usr/bin/nova-metadata-api r, 12 | 13 | /sbin/ldconfig* rix, 14 | 15 | /{,usr/}bin/ r, 16 | /{,usr/}bin/** rix, 17 | 18 | /etc/nova/** r, 19 | /var/lib/nova/** rwk, 20 | /var/log/nova/** rwk, 21 | /{,var/}run/nova/** rwk, 22 | /{,var/}run/lock/nova/** rwk, 23 | 24 | # Allow unconfined sudo to support oslo.rootwrap 25 | # profile makes no attempt to restrict this as this 26 | # is limited by the appropriate rootwrap configuration. 27 | /usr/bin/sudo Ux, 28 | 29 | # Allow ip to run unrestricted for unpriviledged commands 30 | /{,s}bin/ip Ux, 31 | 32 | /tmp/* rw, 33 | /tmp/** rw, 34 | /var/tmp/* a, 35 | 36 | # Required for parsing of managed process cmdline arguments 37 | /proc/*/cmdline r, 38 | 39 | # Required for assessment of current state of networking 40 | /proc/sys/net/** r, 41 | 42 | {% if ubuntu_release <= '12.04' %} 43 | /proc/*/mounts r, 44 | /proc/*/status r, 45 | /proc/*/ns/net r, 46 | {% else %} 47 | owner @{PROC}/@{pid}/mounts r, 48 | owner @{PROC}/@{pid}/status r, 49 | owner @{PROC}/@{pid}/stat r, 50 | owner @{PROC}/@{pid}/ns/net r, 51 | {% endif %} 52 | } 53 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/checks/securetty.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from charmhelpers.contrib.hardening.audits.file import TemplatedFile 16 | from charmhelpers.contrib.hardening.host import TEMPLATES_DIR 17 | from charmhelpers.contrib.hardening import utils 18 | 19 | 20 | def get_audits(): 21 | """Get OS hardening Secure TTY audits. 22 | 23 | :returns: dictionary of audits 24 | """ 25 | audits = [] 26 | audits.append(TemplatedFile('/etc/securetty', SecureTTYContext(), 27 | template_dir=TEMPLATES_DIR, 28 | mode=0o0400, user='root', group='root')) 29 | return audits 30 | 31 | 32 | class SecureTTYContext(object): 33 | 34 | def __call__(self): 35 | settings = utils.get_settings('os') 36 | ctxt = {'ttys': settings['auth']['root_ttys']} 37 | return ctxt 38 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/section-ceph-bluestore-compression: -------------------------------------------------------------------------------- 1 | {# section header omitted as options can belong to multiple sections #} 2 | {% if bluestore_compression_algorithm -%} 3 | bluestore compression algorithm = {{ bluestore_compression_algorithm }} 4 | {% endif -%} 5 | {% if bluestore_compression_mode -%} 6 | bluestore compression mode = {{ bluestore_compression_mode }} 7 | {% endif -%} 8 | {% if bluestore_compression_required_ratio -%} 9 | bluestore compression required ratio = {{ bluestore_compression_required_ratio }} 10 | {% endif -%} 11 | {% if bluestore_compression_min_blob_size -%} 12 | bluestore compression min blob size = {{ bluestore_compression_min_blob_size }} 13 | {% endif -%} 14 | {% if bluestore_compression_min_blob_size_hdd -%} 15 | bluestore compression min blob size hdd = {{ bluestore_compression_min_blob_size_hdd }} 16 | {% endif -%} 17 | {% if bluestore_compression_min_blob_size_ssd -%} 18 | bluestore compression min blob size ssd = {{ bluestore_compression_min_blob_size_ssd }} 19 | {% endif -%} 20 | {% if bluestore_compression_max_blob_size -%} 21 | bluestore compression max blob size = {{ bluestore_compression_max_blob_size }} 22 | {% endif -%} 23 | {% if bluestore_compression_max_blob_size_hdd -%} 24 | bluestore compression max blob size hdd = {{ bluestore_compression_max_blob_size_hdd }} 25 | {% endif -%} 26 | {% if bluestore_compression_max_blob_size_ssd -%} 27 | bluestore compression max blob size ssd = {{ bluestore_compression_max_blob_size_ssd }} 28 | {% endif -%} 29 | -------------------------------------------------------------------------------- /templates/newton/l3_agent.ini: -------------------------------------------------------------------------------- 1 | # newton 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | interface_driver = openvswitch 8 | auth_url = {{ auth_protocol }}://{{ keystone_host }}:{{ auth_port }}/v2.0 9 | auth_region = {{ region }} 10 | admin_tenant_name = {{ service_tenant }} 11 | admin_user = {{ service_username }} 12 | admin_password = {{ service_password }} 13 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 14 | handle_internal_only_routers = {{ handle_internal_only_router }} 15 | {% if plugin == 'n1kv' %} 16 | l3_agent_manager = neutron.agent.l3_agent.L3NATAgentWithStateReport 17 | external_network_bridge = br-int 18 | ovs_use_veth = False 19 | use_namespaces = True 20 | {% else %} 21 | ovs_use_veth = True 22 | {% endif %} 23 | {% if external_configuration_new -%} 24 | gateway_external_network_id = 25 | external_network_bridge = 26 | {% elif ext_net_id %} 27 | gateway_external_network_id = {{ ext_net_id }} 28 | {% else %} 29 | # Set default to deprecated external networking config 30 | external_network_bridge = br-ex 31 | {% endif -%} 32 | agent_mode = {{ agent_mode }} 33 | {% if use_l3ha and keepalived_healthcheck_interval -%} 34 | ha_vrrp_health_check_interval = {{ keepalived_healthcheck_interval }} 35 | {% endif -%} 36 | 37 | [AGENT] 38 | extensions = fwaas 39 | -------------------------------------------------------------------------------- /templates/stein/l3_agent.ini: -------------------------------------------------------------------------------- 1 | # stein 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | interface_driver = openvswitch 8 | root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf 9 | handle_internal_only_routers = {{ handle_internal_only_router }} 10 | {% if plugin == 'n1kv' %} 11 | l3_agent_manager = neutron.agent.l3_agent.L3NATAgentWithStateReport 12 | external_network_bridge = br-int 13 | ovs_use_veth = False 14 | use_namespaces = True 15 | {% else %} 16 | ovs_use_veth = True 17 | {% endif %} 18 | {% if external_configuration_new -%} 19 | gateway_external_network_id = 20 | external_network_bridge = 21 | {% elif ext_net_id %} 22 | gateway_external_network_id = {{ ext_net_id }} 23 | {% else %} 24 | # Set default to deprecated external networking config 25 | external_network_bridge = br-ex 26 | {% endif -%} 27 | agent_mode = {{ agent_mode }} 28 | {% if use_l3ha and keepalived_healthcheck_interval -%} 29 | ha_vrrp_health_check_interval = {{ keepalived_healthcheck_interval }} 30 | {% endif -%} 31 | 32 | [AGENT] 33 | extensions = {{ l3_extension_plugins }} 34 | {% if enable_nfg_logging -%} 35 | [network_log] 36 | {% if nfg_log_rate_limit -%} 37 | rate_limit = {{ nfg_log_rate_limit }} 38 | {% endif -%} 39 | burst_limit = {{ nfg_log_burst_limit }} 40 | {% if nfg_log_output_base -%} 41 | local_output_log_base = {{ nfg_log_output_base }} 42 | {% endif -%} 43 | {% endif -%} 44 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/openstack_https_frontend: -------------------------------------------------------------------------------- 1 | {% if endpoints -%} 2 | {% for ext_port in ext_ports -%} 3 | Listen {{ ext_port }} 4 | {% endfor -%} 5 | {% for address, endpoint, ext, int in endpoints -%} 6 | 7 | ServerName {{ endpoint }} 8 | SSLEngine on 9 | 10 | # This section is based on Mozilla's recommendation 11 | # as the "intermediate" profile as of July 7th, 2020. 12 | # https://wiki.mozilla.org/Security/Server_Side_TLS 13 | SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 14 | SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 15 | SSLHonorCipherOrder off 16 | 17 | SSLCertificateFile /etc/apache2/ssl/{{ namespace }}/cert_{{ endpoint }} 18 | # See LP 1484489 - this is to support <= 2.4.7 and >= 2.4.8 19 | SSLCertificateChainFile /etc/apache2/ssl/{{ namespace }}/cert_{{ endpoint }} 20 | SSLCertificateKeyFile /etc/apache2/ssl/{{ namespace }}/key_{{ endpoint }} 21 | ProxyPass / http://localhost:{{ int }}/ 22 | ProxyPassReverse / http://localhost:{{ int }}/ 23 | ProxyPreserveHost on 24 | RequestHeader set X-Forwarded-Proto "https" 25 | KeepAliveTimeout 75 26 | MaxKeepAliveRequests 1000 27 | 28 | {% endfor -%} 29 | 30 | Order deny,allow 31 | Allow from all 32 | 33 | 34 | Order allow,deny 35 | Allow from all 36 | 37 | {% endif -%} 38 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/openstack_https_frontend.conf: -------------------------------------------------------------------------------- 1 | {% if endpoints -%} 2 | {% for ext_port in ext_ports -%} 3 | Listen {{ ext_port }} 4 | {% endfor -%} 5 | {% for address, endpoint, ext, int in endpoints -%} 6 | 7 | ServerName {{ endpoint }} 8 | SSLEngine on 9 | 10 | # This section is based on Mozilla's recommendation 11 | # as the "intermediate" profile as of July 7th, 2020. 12 | # https://wiki.mozilla.org/Security/Server_Side_TLS 13 | SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 14 | SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 15 | SSLHonorCipherOrder off 16 | 17 | SSLCertificateFile /etc/apache2/ssl/{{ namespace }}/cert_{{ endpoint }} 18 | # See LP 1484489 - this is to support <= 2.4.7 and >= 2.4.8 19 | SSLCertificateChainFile /etc/apache2/ssl/{{ namespace }}/cert_{{ endpoint }} 20 | SSLCertificateKeyFile /etc/apache2/ssl/{{ namespace }}/key_{{ endpoint }} 21 | ProxyPass / http://localhost:{{ int }}/ 22 | ProxyPassReverse / http://localhost:{{ int }}/ 23 | ProxyPreserveHost on 24 | RequestHeader set X-Forwarded-Proto "https" 25 | KeepAliveTimeout 75 26 | MaxKeepAliveRequests 1000 27 | 28 | {% endfor -%} 29 | 30 | Order deny,allow 31 | Allow from all 32 | 33 | 34 | Order allow,deny 35 | Allow from all 36 | 37 | {% endif -%} 38 | -------------------------------------------------------------------------------- /templates/usr.bin.neutron-metadata-agent: -------------------------------------------------------------------------------- 1 | # Last Modified: Fri Apr 1 16:26:34 2016 2 | # Mode: {{aa_profile_mode}} 3 | #include 4 | 5 | /usr/bin/neutron-metadata-agent { 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /usr/bin/neutron-metadata-agent r, 12 | 13 | /sbin/ldconfig* rix, 14 | 15 | /{,usr/}bin/ r, 16 | /{,usr/}bin/** rix, 17 | 18 | /etc/neutron/** r, 19 | /etc/magic r, 20 | /etc/mime.types r, 21 | /var/lib/neutron/** rwk, 22 | /var/log/neutron/** rwk, 23 | /{,var/}run/neutron/** rwk, 24 | /{,var/}run/lock/neutron/** rwk, 25 | /usr/share/file/magic.mgc r, 26 | /usr/share/file/magic/ r, 27 | 28 | # Allow unconfined sudo to support oslo.rootwrap 29 | # profile makes no attempt to restrict this as this 30 | # is limited by the appropriate rootwrap configuration. 31 | /usr/bin/sudo Ux, 32 | 33 | # Allow ip to run unrestricted for unpriviledged commands 34 | /{,s}bin/ip Ux, 35 | 36 | /tmp/* rw, 37 | /tmp/** rw, 38 | /var/tmp/* a, 39 | 40 | # Required for parsing of managed process cmdline arguments 41 | /proc/*/cmdline r, 42 | 43 | # Required for assessment of current state of networking 44 | /proc/sys/net/** r, 45 | 46 | /proc/version r, 47 | 48 | {% if ubuntu_release <= '12.04' %} 49 | /proc/*/mounts r, 50 | /proc/*/status r, 51 | /proc/*/ns/net r, 52 | {% else %} 53 | owner @{PROC}/@{pid}/mounts r, 54 | owner @{PROC}/@{pid}/status r, 55 | owner @{PROC}/@{pid}/stat r, 56 | owner @{PROC}/@{pid}/ns/net r, 57 | {% endif %} 58 | } 59 | -------------------------------------------------------------------------------- /templates/usr.bin.neutron-metering-agent: -------------------------------------------------------------------------------- 1 | # Last Modified: Fri Apr 1 16:26:34 2016 2 | # Mode: {{aa_profile_mode}} 3 | #include 4 | 5 | /usr/bin/neutron-metering-agent { 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /usr/bin/neutron-metering-agent r, 12 | 13 | /sbin/ldconfig* rix, 14 | 15 | /{,usr/}bin/ r, 16 | /{,usr/}bin/** rix, 17 | 18 | /etc/neutron/** r, 19 | /etc/magic r, 20 | /etc/mime.types r, 21 | /var/lib/neutron/** rwk, 22 | /var/log/neutron/** rwk, 23 | /{,var/}run/neutron/** rwk, 24 | /{,var/}run/lock/neutron/** rwk, 25 | 26 | /usr/share/file/magic.mgc r, 27 | /usr/share/file/magic/ r, 28 | 29 | # Allow unconfined sudo to support oslo.rootwrap 30 | # profile makes no attempt to restrict this as this 31 | # is limited by the appropriate rootwrap configuration. 32 | /usr/bin/sudo Ux, 33 | 34 | # Allow ip to run unrestricted for unpriviledged commands 35 | /{,s}bin/ip Ux, 36 | 37 | /tmp/* rw, 38 | /tmp/** rw, 39 | /var/tmp/* a, 40 | 41 | # Required for parsing of managed process cmdline arguments 42 | /proc/*/cmdline r, 43 | 44 | # Required for assessment of current state of networking 45 | /proc/sys/net/** r, 46 | 47 | /proc/version r, 48 | 49 | {% if ubuntu_release <= '12.04' %} 50 | /proc/*/mounts r, 51 | /proc/*/status r, 52 | /proc/*/ns/net r, 53 | {% else %} 54 | owner @{PROC}/@{pid}/mounts r, 55 | owner @{PROC}/@{pid}/status r, 56 | owner @{PROC}/@{pid}/stat r, 57 | owner @{PROC}/@{pid}/ns/net r, 58 | {% endif %} 59 | } 60 | -------------------------------------------------------------------------------- /templates/mitaka/nova.conf: -------------------------------------------------------------------------------- 1 | # mitaka 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | logdir=/var/log/nova 8 | state_path=/var/lib/nova 9 | root_helper=sudo nova-rootwrap /etc/nova/rootwrap.conf 10 | debug = {{ debug }} 11 | verbose= {{ verbose }} 12 | use_syslog = {{ use_syslog }} 13 | api_paste_config=/etc/nova/api-paste.ini 14 | enabled_apis=metadata 15 | multi_host=True 16 | # Access to neutron API services 17 | network_api_class=nova.network.neutronv2.api.API 18 | use_neutron = True 19 | metadata_workers = {{ workers }} 20 | 21 | {% if vendor_data -%} 22 | vendordata_driver = nova.api.metadata.vendordata_json.JsonFileVendorData 23 | vendordata_jsonfile_path = /etc/nova/vendor_data.json 24 | {% endif -%} 25 | 26 | {% if dns_domain -%} 27 | # Per LP#1805645, dhcp_domain needs to be configured for nova-metadata-api 28 | # It gets this information from neutron. 29 | dhcp_domain = {{ dns_domain }} 30 | {% endif -%} 31 | 32 | [neutron] 33 | url={{ quantum_url }} 34 | auth_url={{ auth_protocol }}://{{ keystone_host }}:{{ auth_port }} 35 | auth_type=password 36 | project_domain_name=default 37 | user_domain_name=default 38 | region={{ region }} 39 | project_name={{ service_tenant }} 40 | username={{ service_username }} 41 | password={{ service_password }} 42 | service_metadata_proxy=True 43 | metadata_proxy_shared_secret={{ shared_secret }} 44 | 45 | {% include "section-rabbitmq-oslo" %} 46 | 47 | [oslo_concurrency] 48 | lock_path=/var/lock/nova 49 | -------------------------------------------------------------------------------- /templates/usr.bin.neutron-lbaasv2-agent: -------------------------------------------------------------------------------- 1 | # Last Modified: Fri Apr 1 16:26:34 2016 2 | # Mode: {{aa_profile_mode}} 3 | #include 4 | 5 | /usr/bin/neutron-lbaasv2-agent flags=(attach_disconnected) { 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /usr/bin/neutron-lbaas-agent r, 12 | 13 | /sbin/ldconfig* rix, 14 | 15 | /bin/ r, 16 | /bin/** rix, 17 | /usr/bin/ r, 18 | /usr/bin/** rix, 19 | 20 | /etc/neutron/** r, 21 | /etc/magic r, 22 | /etc/mime.types r, 23 | /var/lib/neutron/** rwk, 24 | /var/log/neutron/** rwk, 25 | /{,var/}run/neutron/** rwk, 26 | /{,var/}run/lock/neutron/** rwk, 27 | 28 | /usr/share/file/magic.mgc r, 29 | /usr/share/file/magic/ r, 30 | 31 | # Allow unconfined sudo to support oslo.rootwrap 32 | # profile makes no attempt to restrict this as this 33 | # is limited by the appropriate rootwrap configuration. 34 | /usr/bin/sudo Ux, 35 | 36 | # Allow ip to run unrestricted for unpriviledged commands 37 | /{,s}bin/ip Ux, 38 | 39 | /tmp/* rw, 40 | /tmp/** rw, 41 | /var/tmp/* a, 42 | 43 | # Required for parsing of managed process cmdline arguments 44 | /proc/*/cmdline r, 45 | 46 | # Required for assessment of current state of networking 47 | /proc/sys/net/** r, 48 | 49 | /proc/version r, 50 | 51 | owner @{PROC}/@{pid}/mounts r, 52 | owner @{PROC}/@{pid}/status r, 53 | owner @{PROC}/@{pid}/stat r, 54 | owner @{PROC}/@{pid}/ns/net r, 55 | # Allow subprocess stat for management of haproxy instances 56 | # which are owned by 'nobody' 57 | @{PROC}/*/stat r, 58 | } 59 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/checks/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from charmhelpers.core.hookenv import ( 16 | log, 17 | DEBUG, 18 | ) 19 | from charmhelpers.contrib.hardening.host.checks import ( 20 | apt, 21 | limits, 22 | login, 23 | minimize_access, 24 | pam, 25 | profile, 26 | securetty, 27 | suid_sgid, 28 | sysctl 29 | ) 30 | 31 | 32 | def run_os_checks(): 33 | log("Starting OS hardening checks.", level=DEBUG) 34 | checks = apt.get_audits() 35 | checks.extend(limits.get_audits()) 36 | checks.extend(login.get_audits()) 37 | checks.extend(minimize_access.get_audits()) 38 | checks.extend(pam.get_audits()) 39 | checks.extend(profile.get_audits()) 40 | checks.extend(securetty.get_audits()) 41 | checks.extend(suid_sgid.get_audits()) 42 | checks.extend(sysctl.get_audits()) 43 | 44 | for check in checks: 45 | log("Running '%s' check" % (check.__class__.__name__), level=DEBUG) 46 | check.ensure_compliance() 47 | 48 | log("OS hardening checks complete.", level=DEBUG) 49 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/alternatives.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ''' Helper for managing alternatives for file conflict resolution ''' 16 | 17 | import subprocess 18 | import shutil 19 | import os 20 | 21 | 22 | def install_alternative(name, target, source, priority=50): 23 | ''' Install alternative configuration ''' 24 | if (os.path.exists(target) and not os.path.islink(target)): 25 | # Move existing file/directory away before installing 26 | shutil.move(target, '{}.bak'.format(target)) 27 | cmd = [ 28 | 'update-alternatives', '--force', '--install', 29 | target, name, source, str(priority) 30 | ] 31 | subprocess.check_call(cmd) 32 | 33 | 34 | def remove_alternative(name, source): 35 | """Remove an installed alternative configuration file 36 | 37 | :param name: string name of the alternative to remove 38 | :param source: string full path to alternative to remove 39 | """ 40 | cmd = [ 41 | 'update-alternatives', '--remove', 42 | name, source 43 | ] 44 | subprocess.check_call(cmd) 45 | -------------------------------------------------------------------------------- /templates/usr.bin.neutron-openvswitch-agent: -------------------------------------------------------------------------------- 1 | # Last Modified: Fri Apr 1 16:26:34 2016 2 | # Mode: {{aa_profile_mode}} 3 | #include 4 | 5 | /usr/bin/neutron-openvswitch-agent { 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /usr/bin/neutron-openvswitch-agent r, 12 | 13 | /sbin/ldconfig* rix, 14 | 15 | /{,usr/}bin/ r, 16 | /{,usr/}bin/** rix, 17 | 18 | /etc/neutron/** r, 19 | /etc/magic r, 20 | /etc/mime.types r, 21 | /etc/udev/udev.conf r, 22 | /var/lib/neutron/** rwk, 23 | /var/log/neutron/** rwk, 24 | /{,var/}run/neutron/** rwk, 25 | /{,var/}run/lock/neutron/** rwk, 26 | /run/udev/* r, 27 | /run/uuidd/request rw, 28 | /sys/kernel/uevent_seqnum r, 29 | 30 | /usr/share/file/magic.mgc r, 31 | /usr/share/file/magic/ r, 32 | 33 | # Allow unconfined sudo to support oslo.rootwrap 34 | # profile makes no attempt to restrict this as this 35 | # is limited by the appropriate rootwrap configuration. 36 | /usr/bin/sudo Ux, 37 | 38 | # Allow ip and ps to run unrestricted for unpriviledged commands 39 | /{,s}bin/ip Ux, 40 | /{,s}bin/ps Ux, 41 | 42 | /tmp/* rw, 43 | /tmp/** rw, 44 | /var/tmp/* a, 45 | 46 | # Required for parsing of managed process cmdline arguments 47 | /proc/*/cmdline r, 48 | 49 | # Required for assessment of current state of networking 50 | /proc/sys/net/** r, 51 | 52 | /proc/version r, 53 | 54 | {% if ubuntu_release <= '12.04' %} 55 | /proc/*/mounts r, 56 | /proc/*/status r, 57 | /proc/*/stat r, 58 | /proc/*/ns/net r, 59 | {% else %} 60 | owner @{PROC}/@{pid}/mounts r, 61 | owner @{PROC}/@{pid}/status r, 62 | owner @{PROC}/@{pid}/ns/net r, 63 | {% endif %} 64 | } 65 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/defaults/ssh.yaml: -------------------------------------------------------------------------------- 1 | # NOTE: this file contains the default configuration for the 'ssh' hardening 2 | # code. If you want to override any settings you must add them to a file 3 | # called hardening.yaml in the root directory of your charm using the 4 | # name 'ssh' as the root key followed by any of the following with new 5 | # values. 6 | 7 | common: 8 | service_name: 'ssh' 9 | network_ipv6_enable: False # (type:boolean) 10 | ports: [22] 11 | remote_hosts: [] 12 | 13 | client: 14 | package: 'openssh-client' 15 | cbc_required: False # (type:boolean) 16 | weak_hmac: False # (type:boolean) 17 | weak_kex: False # (type:boolean) 18 | roaming: False 19 | password_authentication: 'no' 20 | 21 | server: 22 | host_key_files: ['/etc/ssh/ssh_host_rsa_key', '/etc/ssh/ssh_host_dsa_key', 23 | '/etc/ssh/ssh_host_ecdsa_key'] 24 | cbc_required: False # (type:boolean) 25 | weak_hmac: False # (type:boolean) 26 | weak_kex: False # (type:boolean) 27 | allow_root_with_key: False # (type:boolean) 28 | allow_tcp_forwarding: 'no' 29 | allow_agent_forwarding: 'no' 30 | allow_x11_forwarding: 'no' 31 | use_privilege_separation: 'sandbox' 32 | listen_to: ['0.0.0.0'] 33 | use_pam: 'no' 34 | package: 'openssh-server' 35 | password_authentication: 'no' 36 | alive_interval: '600' 37 | alive_count: '3' 38 | sftp_enable: False # (type:boolean) 39 | sftp_group: 'sftponly' 40 | sftp_chroot: '/home/%u' 41 | deny_users: [] 42 | allow_users: [] 43 | deny_groups: [] 44 | allow_groups: [] 45 | print_motd: 'no' 46 | print_last_log: 'no' 47 | use_dns: 'no' 48 | max_auth_tries: 2 49 | max_sessions: 10 50 | -------------------------------------------------------------------------------- /templates/usr.bin.neutron-dhcp-agent: -------------------------------------------------------------------------------- 1 | # Last Modified: Fri Apr 1 16:26:34 2016 2 | # Mode: {{aa_profile_mode}} 3 | #include 4 | 5 | /usr/bin/neutron-dhcp-agent { 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /usr/bin/neutron-dhcp-agent r, 12 | 13 | /sbin/ldconfig* rix, 14 | 15 | /{,usr/}bin/ r, 16 | /{,usr/}bin/** rix, 17 | 18 | /etc/neutron/** r, 19 | /etc/magic r, 20 | /etc/mime.types r, 21 | /var/lib/neutron/** rwk, 22 | /var/log/neutron/** rwk, 23 | /{,var/}run/neutron/** rwk, 24 | /{,var/}run/lock/neutron/** rwk, 25 | /run/uuidd/request rw, 26 | 27 | /usr/share/file/magic.mgc r, 28 | /usr/share/file/magic/ r, 29 | 30 | # Allow unconfined sudo to support oslo.rootwrap 31 | # profile makes no attempt to restrict this as this 32 | # is limited by the appropriate rootwrap configuration. 33 | /usr/bin/sudo Ux, 34 | 35 | /usr/sbin/dnsmasq rix, 36 | 37 | # Allow ip to run unrestricted for unpriviledged commands 38 | /{,s}bin/ip Ux, 39 | 40 | /tmp/* rw, 41 | /tmp/** rw, 42 | /var/tmp/* a, 43 | 44 | # Required for parsing of managed process cmdline arguments 45 | /proc/*/cmdline r, 46 | 47 | # Required for assessment of current state of networking 48 | /proc/sys/net/** r, 49 | 50 | /proc/version r, 51 | 52 | # neutron-dhcp-agent needs to keep track of dnsmasq processes 53 | /proc/*/stat r, 54 | 55 | {% if ubuntu_release <= '12.04' %} 56 | /proc/*/mounts r, 57 | /proc/*/status r, 58 | /proc/*/ns/net r, 59 | {% else %} 60 | owner @{PROC}/@{pid}/mounts r, 61 | owner @{PROC}/@{pid}/status r, 62 | owner @{PROC}/@{pid}/stat r, 63 | owner @{PROC}/@{pid}/ns/net r, 64 | {% endif %} 65 | } 66 | -------------------------------------------------------------------------------- /templates/usr.bin.neutron-l3-agent: -------------------------------------------------------------------------------- 1 | # Last Modified: Fri Apr 1 16:26:34 2016 2 | # Mode: {{aa_profile_mode}} 3 | #include 4 | 5 | /usr/bin/neutron-l3-agent { 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /usr/bin/neutron-l3-agent r, 12 | 13 | /usr/sbin/keepalived rix, 14 | 15 | /sbin/ldconfig* rix, 16 | 17 | /{,usr/}bin/ r, 18 | /{,usr/}bin/** rix, 19 | 20 | /etc/neutron/** r, 21 | /etc/magic r, 22 | /etc/mime.types r, 23 | /var/lib/neutron/** rwk, 24 | /var/log/neutron/** rwk, 25 | /{,var/}run/neutron/** rwk, 26 | /{,var/}run/lock/neutron/** rwk, 27 | /run/uuidd/request rw, 28 | 29 | /usr/share/file/magic.mgc r, 30 | /usr/share/file/magic/ r, 31 | 32 | # Allow unconfined sudo to support oslo.rootwrap 33 | # profile makes no attempt to restrict this as this 34 | # is limited by the appropriate rootwrap configuration. 35 | /usr/bin/sudo Ux, 36 | 37 | # Allow ip to run unrestricted for unpriviledged commands 38 | /{,s}bin/ip Ux, 39 | 40 | /tmp/* rw, 41 | /tmp/** rw, 42 | /var/tmp/* a, 43 | 44 | # Required for parsing of managed process cmdline arguments 45 | /proc/*/cmdline r, 46 | 47 | # Required for assessment of current state of networking 48 | /proc/sys/net/** r, 49 | 50 | /proc/version r, 51 | 52 | # neutron-dhcp-agent needs to keep track of ns-metadata-proxy processes 53 | /proc/*/stat r, 54 | 55 | {% if ubuntu_release <= '12.04' %} 56 | /proc/*/mounts r, 57 | /proc/*/status r, 58 | /proc/*/ns/net r, 59 | {% else %} 60 | owner @{PROC}/@{pid}/mounts r, 61 | owner @{PROC}/@{pid}/status r, 62 | owner @{PROC}/@{pid}/stat r, 63 | owner @{PROC}/@{pid}/ns/net r, 64 | {% endif %} 65 | } 66 | -------------------------------------------------------------------------------- /hooks/charmhelpers/fetch/python/debug.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # Copyright 2014-2015 Canonical Limited. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | import atexit 19 | import sys 20 | 21 | from charmhelpers.fetch.python.rpdb import Rpdb 22 | from charmhelpers.core.hookenv import ( 23 | open_port, 24 | close_port, 25 | ERROR, 26 | log 27 | ) 28 | 29 | __author__ = "Jorge Niedbalski " 30 | 31 | DEFAULT_ADDR = "0.0.0.0" 32 | DEFAULT_PORT = 4444 33 | 34 | 35 | def _error(message): 36 | log(message, level=ERROR) 37 | 38 | 39 | def set_trace(addr=DEFAULT_ADDR, port=DEFAULT_PORT): 40 | """ 41 | Set a trace point using the remote debugger 42 | """ 43 | atexit.register(close_port, port) 44 | try: 45 | log("Starting a remote python debugger session on %s:%s" % (addr, 46 | port)) 47 | open_port(port) 48 | debugger = Rpdb(addr=addr, port=port) 49 | debugger.set_trace(sys._getframe().f_back) 50 | except Exception: 51 | _error("Cannot start a remote debug session on %s:%s" % (addr, 52 | port)) 53 | -------------------------------------------------------------------------------- /templates/newton/nova.conf: -------------------------------------------------------------------------------- 1 | # newton 2 | ############################################################################### 3 | # [ WARNING ] 4 | # Configuration file maintained by Juju. Local changes may be overwritten. 5 | ############################################################################### 6 | [DEFAULT] 7 | logdir=/var/log/nova 8 | state_path=/var/lib/nova 9 | root_helper=sudo nova-rootwrap /etc/nova/rootwrap.conf 10 | debug = {{ debug }} 11 | verbose= {{ verbose }} 12 | use_syslog = {{ use_syslog }} 13 | api_paste_config=/etc/nova/api-paste.ini 14 | enabled_apis=metadata 15 | multi_host=True 16 | # Access to neutron API services 17 | network_api_class=nova.network.neutronv2.api.API 18 | use_neutron = True 19 | metadata_workers = {{ workers }} 20 | 21 | {% if vendor_data or vendor_data_url -%} 22 | [api] 23 | vendordata_providers = {{ vendordata_providers }} 24 | {% if vendor_data -%} 25 | vendordata_jsonfile_path = /etc/nova/vendor_data.json 26 | {% endif -%} 27 | {% if vendor_data_url -%} 28 | vendordata_dynamic_targets = {{ vendor_data_url }} 29 | {% endif -%} 30 | {% endif -%} 31 | 32 | {% if dns_domain -%} 33 | # Per LP#1805645, dhcp_domain needs to be configured for nova-metadata-api 34 | # It gets this information from neutron. 35 | dhcp_domain = {{ dns_domain }} 36 | {% endif -%} 37 | 38 | [neutron] 39 | url={{ quantum_url }} 40 | auth_url={{ auth_protocol }}://{{ keystone_host }}:{{ auth_port }} 41 | auth_type=password 42 | project_domain_name=default 43 | user_domain_name=default 44 | region={{ region }} 45 | project_name={{ service_tenant }} 46 | username={{ service_username }} 47 | password={{ service_password }} 48 | service_metadata_proxy=True 49 | metadata_proxy_shared_secret={{ shared_secret }} 50 | 51 | {% include "section-rabbitmq-oslo" %} 52 | 53 | [oslo_concurrency] 54 | lock_path=/var/lock/nova 55 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/defaults/mysql.yaml: -------------------------------------------------------------------------------- 1 | # NOTE: this file contains the default configuration for the 'mysql' hardening 2 | # code. If you want to override any settings you must add them to a file 3 | # called hardening.yaml in the root directory of your charm using the 4 | # name 'mysql' as the root key followed by any of the following with new 5 | # values. 6 | 7 | hardening: 8 | mysql-conf: /etc/mysql/my.cnf 9 | hardening-conf: /etc/mysql/conf.d/hardening.cnf 10 | 11 | security: 12 | # @see http://www.symantec.com/connect/articles/securing-mysql-step-step 13 | # @see http://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_chroot 14 | chroot: None 15 | 16 | # @see http://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_safe-user-create 17 | safe-user-create: 1 18 | 19 | # @see http://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_secure-auth 20 | secure-auth: 1 21 | 22 | # @see http://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_symbolic-links 23 | skip-symbolic-links: 1 24 | 25 | # @see http://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_skip-show-database 26 | skip-show-database: True 27 | 28 | # @see http://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_local_infile 29 | local-infile: 0 30 | 31 | # @see https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_allow-suspicious-udfs 32 | allow-suspicious-udfs: 0 33 | 34 | # @see https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_automatic_sp_privileges 35 | automatic-sp-privileges: 0 36 | 37 | # @see https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_secure-file-priv 38 | secure-file-priv: /tmp 39 | -------------------------------------------------------------------------------- /hooks/charmhelpers/core/files.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright 2014-2015 Canonical Limited. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | __author__ = 'Jorge Niedbalski ' 19 | 20 | import os 21 | import subprocess 22 | 23 | 24 | def sed(filename, before, after, flags='g'): 25 | """ 26 | Search and replaces the given pattern on filename. 27 | 28 | :param filename: relative or absolute file path. 29 | :param before: expression to be replaced (see 'man sed') 30 | :param after: expression to replace with (see 'man sed') 31 | :param flags: sed-compatible regex flags in example, to make 32 | the search and replace case insensitive, specify ``flags="i"``. 33 | The ``g`` flag is always specified regardless, so you do not 34 | need to remember to include it when overriding this parameter. 35 | :returns: If the sed command exit code was zero then return, 36 | otherwise raise CalledProcessError. 37 | """ 38 | expression = r's/{0}/{1}/{2}'.format(before, 39 | after, flags) 40 | 41 | return subprocess.check_call(["sed", "-i", "-r", "-e", 42 | expression, 43 | os.path.expanduser(filename)]) 44 | -------------------------------------------------------------------------------- /unit_tests/test_actions_openstack_upgrade.py: -------------------------------------------------------------------------------- 1 | from unittest.mock import patch 2 | import os 3 | 4 | from test_utils import ( 5 | CharmTestCase 6 | ) 7 | 8 | os.environ['JUJU_UNIT_NAME'] = 'neutron-gateway' 9 | 10 | import openstack_upgrade 11 | 12 | TO_PATCH = [ 13 | 'do_openstack_upgrade', 14 | 'config_changed', 15 | 'charmhelpers.core.hookenv.log', 16 | 'charmhelpers.contrib.openstack.utils.juju_log', 17 | 'resolve_CONFIGS', 18 | ] 19 | 20 | 21 | class TestNeutronGWUpgradeActions(CharmTestCase): 22 | 23 | def setUp(self): 24 | super(TestNeutronGWUpgradeActions, self).setUp(openstack_upgrade, 25 | TO_PATCH) 26 | 27 | @patch('charmhelpers.contrib.openstack.utils.config') 28 | @patch('charmhelpers.contrib.openstack.utils.action_set') 29 | @patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available') 30 | def test_openstack_upgrade_true(self, upgrade_avail, 31 | action_set, config): 32 | upgrade_avail.return_value = True 33 | config.return_value = True 34 | 35 | openstack_upgrade.openstack_upgrade() 36 | 37 | self.assertTrue(self.do_openstack_upgrade.called) 38 | self.assertTrue(self.config_changed.called) 39 | 40 | @patch('charmhelpers.contrib.openstack.utils.config') 41 | @patch('charmhelpers.contrib.openstack.utils.action_set') 42 | @patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available') 43 | def test_openstack_upgrade_false(self, upgrade_avail, 44 | action_set, config): 45 | upgrade_avail.return_value = True 46 | config.return_value = False 47 | 48 | openstack_upgrade.openstack_upgrade() 49 | 50 | self.assertFalse(self.do_openstack_upgrade.called) 51 | self.assertFalse(self.config_changed.called) 52 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/openstack/templates/memcached.conf: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # [ WARNING ] 3 | # memcached configuration file maintained by Juju 4 | # local changes may be overwritten. 5 | ############################################################################### 6 | 7 | # memcached default config file 8 | # 2003 - Jay Bonci 9 | # This configuration file is read by the start-memcached script provided as 10 | # part of the Debian GNU/Linux distribution. 11 | 12 | # Run memcached as a daemon. This command is implied, and is not needed for the 13 | # daemon to run. See the README.Debian that comes with this package for more 14 | # information. 15 | -d 16 | 17 | # Log memcached's output to /var/log/memcached 18 | logfile /var/log/memcached.log 19 | 20 | # Be verbose 21 | # -v 22 | 23 | # Be even more verbose (print client commands as well) 24 | # -vv 25 | 26 | # Start with a cap of 64 megs of memory. It's reasonable, and the daemon default 27 | # Note that the daemon will grow to this size, but does not start out holding this much 28 | # memory 29 | -m 64 30 | 31 | # Default connection port is 11211 32 | -p {{ memcache_port }} 33 | 34 | # Run the daemon as root. The start-memcached will default to running as root if no 35 | # -u command is present in this config file 36 | -u memcache 37 | 38 | # Specify which IP address to listen on. The default is to listen on all IP addresses 39 | # This parameter is one of the only security measures that memcached has, so make sure 40 | # it's listening on a firewalled interface. 41 | -l {{ memcache_server }} 42 | 43 | # Limit the number of simultaneous incoming connections. The daemon default is 1024 44 | # -c 1024 45 | 46 | # Lock down all paged memory. Consult with the README and homepage before you do this 47 | # -k 48 | 49 | # Return error when memory is exhausted (rather than removing items) 50 | # -M 51 | 52 | # Maximize core file limit 53 | # -r 54 | -------------------------------------------------------------------------------- /hooks/charmhelpers/cli/unitdata.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from . import cmdline 16 | from charmhelpers.core import unitdata 17 | 18 | 19 | @cmdline.subcommand_builder('unitdata', description="Store and retrieve data") 20 | def unitdata_cmd(subparser): 21 | nested = subparser.add_subparsers() 22 | 23 | get_cmd = nested.add_parser('get', help='Retrieve data') 24 | get_cmd.add_argument('key', help='Key to retrieve the value of') 25 | get_cmd.set_defaults(action='get', value=None) 26 | 27 | getrange_cmd = nested.add_parser('getrange', help='Retrieve multiple data') 28 | getrange_cmd.add_argument('key', metavar='prefix', 29 | help='Prefix of the keys to retrieve') 30 | getrange_cmd.set_defaults(action='getrange', value=None) 31 | 32 | set_cmd = nested.add_parser('set', help='Store data') 33 | set_cmd.add_argument('key', help='Key to set') 34 | set_cmd.add_argument('value', help='Value to store') 35 | set_cmd.set_defaults(action='set') 36 | 37 | def _unitdata_cmd(action, key, value): 38 | if action == 'get': 39 | return unitdata.kv().get(key) 40 | elif action == 'getrange': 41 | return unitdata.kv().getrange(key) 42 | elif action == 'set': 43 | unitdata.kv().set(key, value) 44 | unitdata.kv().flush() 45 | return '' 46 | return _unitdata_cmd 47 | -------------------------------------------------------------------------------- /actions/security_checklist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright 2019 Canonical Ltd 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import configparser 18 | import os 19 | import sys 20 | 21 | _path = os.path.dirname(os.path.realpath(__file__)) 22 | _hooks = os.path.abspath(os.path.join(_path, '../hooks')) 23 | 24 | 25 | def _add_path(path): 26 | if path not in sys.path: 27 | sys.path.insert(1, path) 28 | 29 | 30 | _add_path(_hooks) 31 | 32 | 33 | import charmhelpers.contrib.openstack.audits as audits 34 | from charmhelpers.contrib.openstack.audits import ( 35 | openstack_security_guide, 36 | ) 37 | 38 | 39 | # Via the openstack_security_guide above, we are running the following 40 | # security assertions automatically: 41 | # 42 | # - Check-Neutron-01 - validate-file-ownership 43 | # - Check-Neutron-02 - validate-file-permissions 44 | 45 | 46 | def main(): 47 | config = { 48 | 'audit_type': audits.AuditType.OpenStackSecurityGuide, 49 | 'files': openstack_security_guide.FILE_ASSERTIONS['neutron-gateway'], 50 | 'excludes': [ 51 | 'validate-uses-keystone', 52 | 'validate-uses-tls-for-glance', 53 | 'validate-uses-tls-for-keystone', 54 | ], 55 | } 56 | conf = configparser.ConfigParser() 57 | conf.read("/etc/neutron/neutron.conf") 58 | config['neutron_config'] = dict(conf) 59 | return audits.action_parse_results(audits.run(config)) 60 | 61 | 62 | if __name__ == "__main__": 63 | sys.exit(main()) 64 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/checks/minimize_access.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from charmhelpers.contrib.hardening.audits.file import ( 16 | FilePermissionAudit, 17 | ReadOnly, 18 | ) 19 | from charmhelpers.contrib.hardening import utils 20 | 21 | 22 | def get_audits(): 23 | """Get OS hardening access audits. 24 | 25 | :returns: dictionary of audits 26 | """ 27 | audits = [] 28 | settings = utils.get_settings('os') 29 | 30 | # Remove write permissions from $PATH folders for all regular users. 31 | # This prevents changing system-wide commands from normal users. 32 | path_folders = {'/usr/local/sbin', 33 | '/usr/local/bin', 34 | '/usr/sbin', 35 | '/usr/bin', 36 | '/bin'} 37 | extra_user_paths = settings['environment']['extra_user_paths'] 38 | path_folders.update(extra_user_paths) 39 | audits.append(ReadOnly(path_folders)) 40 | 41 | # Only allow the root user to have access to the shadow file. 42 | audits.append(FilePermissionAudit('/etc/shadow', 'root', 'root', 0o0600)) 43 | 44 | if 'change_user' not in settings['security']['users_allow']: 45 | # su should only be accessible to user and group root, unless it is 46 | # expressly defined to allow users to change to root via the 47 | # security_users_allow config option. 48 | audits.append(FilePermissionAudit('/bin/su', 'root', 'root', 0o750)) 49 | 50 | return audits 51 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/checks/profile.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from charmhelpers.contrib.hardening.audits.file import TemplatedFile 16 | from charmhelpers.contrib.hardening.host import TEMPLATES_DIR 17 | from charmhelpers.contrib.hardening import utils 18 | 19 | 20 | def get_audits(): 21 | """Get OS hardening profile audits. 22 | 23 | :returns: dictionary of audits 24 | """ 25 | audits = [] 26 | 27 | settings = utils.get_settings('os') 28 | # If core dumps are not enabled, then don't allow core dumps to be 29 | # created as they may contain sensitive information. 30 | if not settings['security']['kernel_enable_core_dump']: 31 | audits.append(TemplatedFile('/etc/profile.d/pinerolo_profile.sh', 32 | ProfileContext(), 33 | template_dir=TEMPLATES_DIR, 34 | mode=0o0755, user='root', group='root')) 35 | if settings['security']['ssh_tmout']: 36 | audits.append(TemplatedFile('/etc/profile.d/99-hardening.sh', 37 | ProfileContext(), 38 | template_dir=TEMPLATES_DIR, 39 | mode=0o0644, user='root', group='root')) 40 | return audits 41 | 42 | 43 | class ProfileContext(object): 44 | 45 | def __call__(self): 46 | settings = utils.get_settings('os') 47 | ctxt = {'ssh_tmout': 48 | settings['security']['ssh_tmout']} 49 | return ctxt 50 | -------------------------------------------------------------------------------- /hooks/charmhelpers/fetch/python/rpdb.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Remote Python Debugger (pdb wrapper).""" 16 | 17 | import pdb 18 | import socket 19 | import sys 20 | 21 | __author__ = "Bertrand Janin " 22 | __version__ = "0.1.3" 23 | 24 | 25 | class Rpdb(pdb.Pdb): 26 | 27 | def __init__(self, addr="127.0.0.1", port=4444): 28 | """Initialize the socket and initialize pdb.""" 29 | 30 | # Backup stdin and stdout before replacing them by the socket handle 31 | self.old_stdout = sys.stdout 32 | self.old_stdin = sys.stdin 33 | 34 | # Open a 'reusable' socket to let the webapp reload on the same port 35 | self.skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 36 | self.skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) 37 | self.skt.bind((addr, port)) 38 | self.skt.listen(1) 39 | (clientsocket, address) = self.skt.accept() 40 | handle = clientsocket.makefile('rw') 41 | pdb.Pdb.__init__(self, completekey='tab', stdin=handle, stdout=handle) 42 | sys.stdout = sys.stdin = handle 43 | 44 | def shutdown(self): 45 | """Revert stdin and stdout, close the socket.""" 46 | sys.stdout = self.old_stdout 47 | sys.stdin = self.old_stdin 48 | self.skt.close() 49 | self.set_continue() 50 | 51 | def do_continue(self, arg): 52 | """Stop all operation on ``continue``.""" 53 | self.shutdown() 54 | return 1 55 | 56 | do_EOF = do_quit = do_exit = do_c = do_cont = do_continue 57 | -------------------------------------------------------------------------------- /actions.yaml: -------------------------------------------------------------------------------- 1 | cleanup: 2 | description: | 3 | Clean up after the Neutron agents. 4 | params: 5 | i-really-mean-it: 6 | type: boolean 7 | default: false 8 | description: | 9 | The default false will not run the action, set to true to perform 10 | cleanup. 11 | . 12 | WARNING: Running this action will interrupt instance connectivity and 13 | it will not be restored until either Neutron agents or a different 14 | SDN reprograms connectivity on the gateway. 15 | . 16 | NOTE: The unit must be paused prior to running this action. 17 | required: 18 | - i-really-mean-it 19 | openstack-upgrade: 20 | description: Perform openstack upgrades. Config option action-managed-upgrade must be set to True. 21 | pause: 22 | description: Pause the neutron-gateway unit. 23 | resume: 24 | description: Resume the neutron-gateway unit. 25 | security-checklist: 26 | description: Validate the running configuration against the OpenStack security guides checklist 27 | restart-services: 28 | description: | 29 | Restarts services this charm manages. 30 | params: 31 | deferred-only: 32 | type: boolean 33 | default: false 34 | description: | 35 | Restart all deferred services. 36 | services: 37 | type: string 38 | default: "" 39 | description: | 40 | List of services to restart. 41 | run-hooks: 42 | type: boolean 43 | default: true 44 | description: | 45 | Run any hooks which have been deferred. 46 | run-deferred-hooks: 47 | description: | 48 | Run deferable hooks and restart services. 49 | . 50 | NOTE: Service will be restarted as needed irrespective of enable-auto-restarts 51 | show-deferred-events: 52 | description: | 53 | Show the outstanding restarts 54 | show-routers: 55 | description: Shows a list of routers hosted on the neutron-gateway unit. 56 | show-dhcp-networks: 57 | description: Shows a list of DHCP networks hosted on the neutron-gateway unit. 58 | show-loadbalancers: 59 | description: Shows a list of LBaasV2 load-balancers hosted on the neutron-gateway unit. 60 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/defaults/os.yaml: -------------------------------------------------------------------------------- 1 | # NOTE: this file contains the default configuration for the 'os' hardening 2 | # code. If you want to override any settings you must add them to a file 3 | # called hardening.yaml in the root directory of your charm using the 4 | # name 'os' as the root key followed by any of the following with new 5 | # values. 6 | 7 | general: 8 | desktop_enable: False # (type:boolean) 9 | 10 | environment: 11 | extra_user_paths: [] 12 | umask: 027 13 | root_path: / 14 | 15 | auth: 16 | pw_max_age: 60 17 | # discourage password cycling 18 | pw_min_age: 7 19 | retries: 5 20 | lockout_time: 600 21 | timeout: 60 22 | allow_homeless: False # (type:boolean) 23 | pam_passwdqc_enable: True # (type:boolean) 24 | pam_passwdqc_options: 'min=disabled,disabled,16,12,8' 25 | root_ttys: 26 | console 27 | tty1 28 | tty2 29 | tty3 30 | tty4 31 | tty5 32 | tty6 33 | uid_min: 1000 34 | gid_min: 1000 35 | sys_uid_min: 100 36 | sys_uid_max: 999 37 | sys_gid_min: 100 38 | sys_gid_max: 999 39 | chfn_restrict: 40 | 41 | security: 42 | users_allow: [] 43 | suid_sgid_enforce: True # (type:boolean) 44 | # user-defined blacklist and whitelist 45 | suid_sgid_blacklist: [] 46 | suid_sgid_whitelist: [] 47 | # if this is True, remove any suid/sgid bits from files that were not in the whitelist 48 | suid_sgid_dry_run_on_unknown: False # (type:boolean) 49 | suid_sgid_remove_from_unknown: False # (type:boolean) 50 | # remove packages with known issues 51 | packages_clean: True # (type:boolean) 52 | packages_list: 53 | xinetd 54 | inetd 55 | ypserv 56 | telnet-server 57 | rsh-server 58 | rsync 59 | kernel_enable_module_loading: True # (type:boolean) 60 | kernel_enable_core_dump: False # (type:boolean) 61 | ssh_tmout: 300 62 | 63 | sysctl: 64 | kernel_secure_sysrq: 244 # 4 + 16 + 32 + 64 + 128 65 | kernel_enable_sysrq: False # (type:boolean) 66 | forwarding: False # (type:boolean) 67 | ipv6_enable: False # (type:boolean) 68 | arp_restricted: True # (type:boolean) 69 | -------------------------------------------------------------------------------- /hooks/charmhelpers/core/host_factory/centos.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import yum 3 | import os 4 | 5 | from charmhelpers.core.strutils import BasicStringComparator 6 | 7 | 8 | class CompareHostReleases(BasicStringComparator): 9 | """Provide comparisons of Host releases. 10 | 11 | Use in the form of 12 | 13 | if CompareHostReleases(release) > 'trusty': 14 | # do something with mitaka 15 | """ 16 | 17 | def __init__(self, item): 18 | raise NotImplementedError( 19 | "CompareHostReleases() is not implemented for CentOS") 20 | 21 | 22 | def service_available(service_name): 23 | # """Determine whether a system service is available.""" 24 | if os.path.isdir('/run/systemd/system'): 25 | cmd = ['systemctl', 'is-enabled', service_name] 26 | else: 27 | cmd = ['service', service_name, 'is-enabled'] 28 | return subprocess.call(cmd) == 0 29 | 30 | 31 | def add_new_group(group_name, system_group=False, gid=None): 32 | cmd = ['groupadd'] 33 | if gid: 34 | cmd.extend(['--gid', str(gid)]) 35 | if system_group: 36 | cmd.append('-r') 37 | cmd.append(group_name) 38 | subprocess.check_call(cmd) 39 | 40 | 41 | def lsb_release(): 42 | """Return /etc/os-release in a dict.""" 43 | d = {} 44 | with open('/etc/os-release', 'r') as lsb: 45 | for l in lsb: 46 | s = l.split('=') 47 | if len(s) != 2: 48 | continue 49 | d[s[0].strip()] = s[1].strip() 50 | return d 51 | 52 | 53 | def cmp_pkgrevno(package, revno, pkgcache=None): 54 | """Compare supplied revno with the revno of the installed package. 55 | 56 | * 1 => Installed revno is greater than supplied arg 57 | * 0 => Installed revno is the same as supplied arg 58 | * -1 => Installed revno is less than supplied arg 59 | 60 | This function imports YumBase function if the pkgcache argument 61 | is None. 62 | """ 63 | if not pkgcache: 64 | y = yum.YumBase() 65 | packages = y.doPackageLists() 66 | pkgcache = {i.Name: i.version for i in packages['installed']} 67 | pkg = pkgcache[package] 68 | if pkg > revno: 69 | return 1 70 | if pkg < revno: 71 | return -1 72 | return 0 73 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/checks/limits.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from charmhelpers.contrib.hardening.audits.file import ( 16 | DirectoryPermissionAudit, 17 | TemplatedFile, 18 | ) 19 | from charmhelpers.contrib.hardening.host import TEMPLATES_DIR 20 | from charmhelpers.contrib.hardening import utils 21 | 22 | 23 | def get_audits(): 24 | """Get OS hardening security limits audits. 25 | 26 | :returns: dictionary of audits 27 | """ 28 | audits = [] 29 | settings = utils.get_settings('os') 30 | 31 | # Ensure that the /etc/security/limits.d directory is only writable 32 | # by the root user, but others can execute and read. 33 | audits.append(DirectoryPermissionAudit('/etc/security/limits.d', 34 | user='root', group='root', 35 | mode=0o755)) 36 | 37 | # If core dumps are not enabled, then don't allow core dumps to be 38 | # created as they may contain sensitive information. 39 | if not settings['security']['kernel_enable_core_dump']: 40 | audits.append(TemplatedFile('/etc/security/limits.d/10.hardcore.conf', 41 | SecurityLimitsContext(), 42 | template_dir=TEMPLATES_DIR, 43 | user='root', group='root', mode=0o0440)) 44 | return audits 45 | 46 | 47 | class SecurityLimitsContext(object): 48 | 49 | def __call__(self): 50 | settings = utils.get_settings('os') 51 | ctxt = {'disable_core_dump': 52 | not settings['security']['kernel_enable_core_dump']} 53 | return ctxt 54 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/audits/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | 16 | class BaseAudit(object): # NO-QA 17 | """Base class for hardening checks. 18 | 19 | The lifecycle of a hardening check is to first check to see if the system 20 | is in compliance for the specified check. If it is not in compliance, the 21 | check method will return a value which will be supplied to the. 22 | """ 23 | def __init__(self, *args, **kwargs): 24 | self.unless = kwargs.get('unless', None) 25 | super(BaseAudit, self).__init__() 26 | 27 | def ensure_compliance(self): 28 | """Checks to see if the current hardening check is in compliance or 29 | not. 30 | 31 | If the check that is performed is not in compliance, then an exception 32 | should be raised. 33 | """ 34 | pass 35 | 36 | def _take_action(self): 37 | """Determines whether to perform the action or not. 38 | 39 | Checks whether or not an action should be taken. This is determined by 40 | the truthy value for the unless parameter. If unless is a callback 41 | method, it will be invoked with no parameters in order to determine 42 | whether or not the action should be taken. Otherwise, the truthy value 43 | of the unless attribute will determine if the action should be 44 | performed. 45 | """ 46 | # Do the action if there isn't an unless override. 47 | if self.unless is None: 48 | return True 49 | 50 | # Invoke the callback if there is one. 51 | if hasattr(self.unless, '__call__'): 52 | return not self.unless() 53 | 54 | return not self.unless 55 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/ssh/templates/ssh_config: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # WARNING: This configuration file is maintained by Juju. Local changes may 3 | # be overwritten. 4 | ############################################################################### 5 | # This is the ssh client system-wide configuration file. See 6 | # ssh_config(5) for more information. This file provides defaults for 7 | # users, and the values can be changed in per-user configuration files 8 | # or on the command line. 9 | 10 | # Configuration data is parsed as follows: 11 | # 1. command line options 12 | # 2. user-specific file 13 | # 3. system-wide file 14 | # Any configuration value is only changed the first time it is set. 15 | # Thus, host-specific definitions should be at the beginning of the 16 | # configuration file, and defaults at the end. 17 | 18 | # Site-wide defaults for some commonly used options. For a comprehensive 19 | # list of available options, their meanings and defaults, please see the 20 | # ssh_config(5) man page. 21 | 22 | # Restrict the following configuration to be limited to this Host. 23 | {% if remote_hosts -%} 24 | Host {{ ' '.join(remote_hosts) }} 25 | {% endif %} 26 | ForwardAgent no 27 | ForwardX11 no 28 | ForwardX11Trusted yes 29 | RhostsRSAAuthentication no 30 | RSAAuthentication yes 31 | PasswordAuthentication {{ password_auth_allowed }} 32 | HostbasedAuthentication no 33 | GSSAPIAuthentication no 34 | GSSAPIDelegateCredentials no 35 | GSSAPIKeyExchange no 36 | GSSAPITrustDNS no 37 | BatchMode no 38 | CheckHostIP yes 39 | AddressFamily {{ addr_family }} 40 | ConnectTimeout 0 41 | StrictHostKeyChecking ask 42 | IdentityFile ~/.ssh/identity 43 | IdentityFile ~/.ssh/id_rsa 44 | IdentityFile ~/.ssh/id_dsa 45 | # The port at the destination should be defined 46 | {% for port in ports -%} 47 | Port {{ port }} 48 | {% endfor %} 49 | Protocol 2 50 | Cipher 3des 51 | {% if ciphers -%} 52 | Ciphers {{ ciphers }} 53 | {%- endif %} 54 | {% if macs -%} 55 | MACs {{ macs }} 56 | {%- endif %} 57 | {% if kexs -%} 58 | KexAlgorithms {{ kexs }} 59 | {%- endif %} 60 | EscapeChar ~ 61 | Tunnel no 62 | TunnelDevice any:any 63 | PermitLocalCommand no 64 | VisualHostKey no 65 | RekeyLimit 1G 1h 66 | SendEnv LANG LC_* 67 | HashKnownHosts yes 68 | {% if roaming -%} 69 | UseRoaming {{ roaming }} 70 | {% endif %} 71 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/templates/modules: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # WARNING: This configuration file is maintained by Juju. Local changes may 3 | # be overwritten. 4 | ############################################################################### 5 | # /etc/modules: kernel modules to load at boot time. 6 | # 7 | # This file contains the names of kernel modules that should be loaded 8 | # at boot time, one per line. Lines beginning with "#" are ignored. 9 | # Parameters can be specified after the module name. 10 | 11 | # Arch 12 | # ---- 13 | # 14 | # Modules for certains builds, contains support modules and some CPU-specific optimizations. 15 | 16 | {% if arch == "x86_64" -%} 17 | # Optimize for x86_64 cryptographic features 18 | twofish-x86_64-3way 19 | twofish-x86_64 20 | aes-x86_64 21 | salsa20-x86_64 22 | blowfish-x86_64 23 | {% endif -%} 24 | 25 | {% if cpuVendor == "intel" -%} 26 | # Intel-specific optimizations 27 | ghash-clmulni-intel 28 | aesni-intel 29 | kvm-intel 30 | {% endif -%} 31 | 32 | {% if cpuVendor == "amd" -%} 33 | # AMD-specific optimizations 34 | kvm-amd 35 | {% endif -%} 36 | 37 | kvm 38 | 39 | 40 | # Crypto 41 | # ------ 42 | 43 | # Some core modules which comprise strong cryptography. 44 | blowfish_common 45 | blowfish_generic 46 | ctr 47 | cts 48 | lrw 49 | lzo 50 | rmd160 51 | rmd256 52 | rmd320 53 | serpent 54 | sha512_generic 55 | twofish_common 56 | twofish_generic 57 | xts 58 | zlib 59 | 60 | 61 | # Drivers 62 | # ------- 63 | 64 | # Basics 65 | lp 66 | rtc 67 | loop 68 | 69 | # Filesystems 70 | ext2 71 | btrfs 72 | 73 | {% if desktop_enable -%} 74 | # Desktop 75 | psmouse 76 | snd 77 | snd_ac97_codec 78 | snd_intel8x0 79 | snd_page_alloc 80 | snd_pcm 81 | snd_timer 82 | soundcore 83 | usbhid 84 | {% endif -%} 85 | 86 | # Lib 87 | # --- 88 | xz 89 | 90 | 91 | # Net 92 | # --- 93 | 94 | # All packets needed for netfilter rules (ie iptables, ebtables). 95 | ip_tables 96 | x_tables 97 | iptable_filter 98 | iptable_nat 99 | 100 | # Targets 101 | ipt_LOG 102 | ipt_REJECT 103 | 104 | # Modules 105 | xt_connlimit 106 | xt_tcpudp 107 | xt_recent 108 | xt_limit 109 | xt_conntrack 110 | nf_conntrack 111 | nf_conntrack_ipv4 112 | nf_defrag_ipv4 113 | xt_state 114 | nf_nat 115 | 116 | # Addons 117 | xt_pknock -------------------------------------------------------------------------------- /hooks/charmhelpers/osplatform.py: -------------------------------------------------------------------------------- 1 | import platform 2 | import os 3 | 4 | 5 | def get_platform(): 6 | """Return the current OS platform. 7 | 8 | For example: if current os platform is Ubuntu then a string "ubuntu" 9 | will be returned (which is the name of the module). 10 | This string is used to decide which platform module should be imported. 11 | """ 12 | current_platform = _get_current_platform() 13 | 14 | if "Ubuntu" in current_platform: 15 | return "ubuntu" 16 | elif "CentOS" in current_platform: 17 | return "centos" 18 | elif "debian" in current_platform or "Debian" in current_platform: 19 | # Stock Python does not detect Ubuntu and instead returns debian. 20 | # Or at least it does in some build environments like Travis CI 21 | return "ubuntu" 22 | elif "elementary" in current_platform: 23 | # ElementaryOS fails to run tests locally without this. 24 | return "ubuntu" 25 | elif "Pop!_OS" in current_platform: 26 | # Pop!_OS also fails to run tests locally without this. 27 | return "ubuntu" 28 | else: 29 | raise RuntimeError("This module is not supported on {}." 30 | .format(current_platform)) 31 | 32 | 33 | def _get_current_platform(): 34 | """Return the current platform information for the OS. 35 | 36 | Attempts to lookup linux distribution information from the platform 37 | module for releases of python < 3.7. For newer versions of python, 38 | the platform is determined from the /etc/os-release file. 39 | """ 40 | # linux_distribution is deprecated and will be removed in Python 3.7 41 | # Warnings *not* disabled, as we certainly need to fix this. 42 | if hasattr(platform, 'linux_distribution'): 43 | tuple_platform = platform.linux_distribution() 44 | current_platform = tuple_platform[0] 45 | else: 46 | current_platform = _get_platform_from_fs() 47 | 48 | return current_platform 49 | 50 | 51 | def _get_platform_from_fs(): 52 | """Get Platform from /etc/os-release.""" 53 | with open(os.path.join(os.sep, 'etc', 'os-release')) as fin: 54 | content = dict( 55 | line.split('=', 1) 56 | for line in fin.read().splitlines() 57 | if '=' in line 58 | ) 59 | for k, v in content.items(): 60 | content[k] = v.strip('"') 61 | return content["NAME"] 62 | -------------------------------------------------------------------------------- /hooks/charmhelpers/payload/archive.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import tarfile 17 | import zipfile 18 | from charmhelpers.core import ( 19 | host, 20 | hookenv, 21 | ) 22 | 23 | 24 | class ArchiveError(Exception): 25 | pass 26 | 27 | 28 | def get_archive_handler(archive_name): 29 | if os.path.isfile(archive_name): 30 | if tarfile.is_tarfile(archive_name): 31 | return extract_tarfile 32 | elif zipfile.is_zipfile(archive_name): 33 | return extract_zipfile 34 | else: 35 | # look at the file name 36 | for ext in ('.tar', '.tar.gz', '.tgz', 'tar.bz2', '.tbz2', '.tbz'): 37 | if archive_name.endswith(ext): 38 | return extract_tarfile 39 | for ext in ('.zip', '.jar'): 40 | if archive_name.endswith(ext): 41 | return extract_zipfile 42 | 43 | 44 | def archive_dest_default(archive_name): 45 | archive_file = os.path.basename(archive_name) 46 | return os.path.join(hookenv.charm_dir(), "archives", archive_file) 47 | 48 | 49 | def extract(archive_name, destpath=None): 50 | handler = get_archive_handler(archive_name) 51 | if handler: 52 | if not destpath: 53 | destpath = archive_dest_default(archive_name) 54 | if not os.path.isdir(destpath): 55 | host.mkdir(destpath) 56 | handler(archive_name, destpath) 57 | return destpath 58 | else: 59 | raise ArchiveError("No handler for archive") 60 | 61 | 62 | def extract_tarfile(archive_name, destpath): 63 | "Unpack a tar archive, optionally compressed" 64 | archive = tarfile.open(archive_name) 65 | archive.extractall(destpath) 66 | 67 | 68 | def extract_zipfile(archive_name, destpath): 69 | "Unpack a zip file" 70 | archive = zipfile.ZipFile(archive_name) 71 | archive.extractall(destpath) 72 | -------------------------------------------------------------------------------- /hooks/charmhelpers/core/kernel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright 2014-2015 Canonical Limited. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | import re 19 | import subprocess 20 | 21 | from charmhelpers.osplatform import get_platform 22 | from charmhelpers.core.hookenv import ( 23 | log, 24 | INFO 25 | ) 26 | 27 | __platform__ = get_platform() 28 | if __platform__ == "ubuntu": 29 | from charmhelpers.core.kernel_factory.ubuntu import ( # NOQA:F401 30 | persistent_modprobe, 31 | update_initramfs, 32 | ) # flake8: noqa -- ignore F401 for this import 33 | elif __platform__ == "centos": 34 | from charmhelpers.core.kernel_factory.centos import ( # NOQA:F401 35 | persistent_modprobe, 36 | update_initramfs, 37 | ) # flake8: noqa -- ignore F401 for this import 38 | 39 | __author__ = "Jorge Niedbalski " 40 | 41 | 42 | def modprobe(module, persist=True): 43 | """Load a kernel module and configure for auto-load on reboot.""" 44 | cmd = ['modprobe', module] 45 | 46 | log('Loading kernel module %s' % module, level=INFO) 47 | 48 | subprocess.check_call(cmd) 49 | if persist: 50 | persistent_modprobe(module) 51 | 52 | 53 | def rmmod(module, force=False): 54 | """Remove a module from the linux kernel""" 55 | cmd = ['rmmod'] 56 | if force: 57 | cmd.append('-f') 58 | cmd.append(module) 59 | log('Removing kernel module %s' % module, level=INFO) 60 | return subprocess.check_call(cmd) 61 | 62 | 63 | def lsmod(): 64 | """Shows what kernel modules are currently loaded""" 65 | return subprocess.check_output(['lsmod'], 66 | universal_newlines=True) 67 | 68 | 69 | def is_module_loaded(module): 70 | """Checks if a kernel module is already loaded""" 71 | matches = re.findall('^%s[ ]+' % module, lsmod(), re.M) 72 | return len(matches) > 0 73 | -------------------------------------------------------------------------------- /hooks/charmhelpers/payload/execd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright 2014-2015 Canonical Limited. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import os 18 | import sys 19 | import subprocess 20 | from charmhelpers.core import hookenv 21 | 22 | 23 | def default_execd_dir(): 24 | return os.path.join(os.environ['CHARM_DIR'], 'exec.d') 25 | 26 | 27 | def execd_module_paths(execd_dir=None): 28 | """Generate a list of full paths to modules within execd_dir.""" 29 | if not execd_dir: 30 | execd_dir = default_execd_dir() 31 | 32 | if not os.path.exists(execd_dir): 33 | return 34 | 35 | for subpath in os.listdir(execd_dir): 36 | module = os.path.join(execd_dir, subpath) 37 | if os.path.isdir(module): 38 | yield module 39 | 40 | 41 | def execd_submodule_paths(command, execd_dir=None): 42 | """Generate a list of full paths to the specified command within exec_dir. 43 | """ 44 | for module_path in execd_module_paths(execd_dir): 45 | path = os.path.join(module_path, command) 46 | if os.access(path, os.X_OK) and os.path.isfile(path): 47 | yield path 48 | 49 | 50 | def execd_run(command, execd_dir=None, die_on_error=True, stderr=subprocess.STDOUT): 51 | """Run command for each module within execd_dir which defines it.""" 52 | for submodule_path in execd_submodule_paths(command, execd_dir): 53 | try: 54 | subprocess.check_output(submodule_path, stderr=stderr, 55 | universal_newlines=True) 56 | except subprocess.CalledProcessError as e: 57 | hookenv.log("Error ({}) running {}. Output: {}".format( 58 | e.returncode, e.cmd, e.output)) 59 | if die_on_error: 60 | sys.exit(e.returncode) 61 | 62 | 63 | def execd_preinstall(execd_dir=None): 64 | """Run charm-pre-install for each module within execd_dir.""" 65 | execd_run('charm-pre-install', execd_dir=execd_dir) 66 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/storage/linux/bcache.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | import os 15 | import json 16 | 17 | from charmhelpers.core.hookenv import log 18 | 19 | stats_intervals = ['stats_day', 'stats_five_minute', 20 | 'stats_hour', 'stats_total'] 21 | 22 | SYSFS = '/sys' 23 | 24 | 25 | class Bcache(object): 26 | """Bcache behaviour 27 | """ 28 | 29 | def __init__(self, cachepath): 30 | self.cachepath = cachepath 31 | 32 | @classmethod 33 | def fromdevice(cls, devname): 34 | return cls('{}/block/{}/bcache'.format(SYSFS, devname)) 35 | 36 | def __str__(self): 37 | return self.cachepath 38 | 39 | def get_stats(self, interval): 40 | """Get cache stats 41 | """ 42 | intervaldir = 'stats_{}'.format(interval) 43 | path = "{}/{}".format(self.cachepath, intervaldir) 44 | out = dict() 45 | for elem in os.listdir(path): 46 | out[elem] = open('{}/{}'.format(path, elem)).read().strip() 47 | return out 48 | 49 | 50 | def get_bcache_fs(): 51 | """Return all cache sets 52 | """ 53 | cachesetroot = "{}/fs/bcache".format(SYSFS) 54 | try: 55 | dirs = os.listdir(cachesetroot) 56 | except OSError: 57 | log("No bcache fs found") 58 | return [] 59 | cacheset = set([Bcache('{}/{}'.format(cachesetroot, d)) for d in dirs if not d.startswith('register')]) 60 | return cacheset 61 | 62 | 63 | def get_stats_action(cachespec, interval): 64 | """Action for getting bcache statistics for a given cachespec. 65 | Cachespec can either be a device name, eg. 'sdb', which will retrieve 66 | cache stats for the given device, or 'global', which will retrieve stats 67 | for all cachesets 68 | """ 69 | if cachespec == 'global': 70 | caches = get_bcache_fs() 71 | else: 72 | caches = [Bcache.fromdevice(cachespec)] 73 | res = dict((c.cachepath, c.get_stats(interval)) for c in caches) 74 | return json.dumps(res, indent=4, separators=(',', ': ')) 75 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/templating.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | 17 | from charmhelpers.core.hookenv import ( 18 | log, 19 | DEBUG, 20 | WARNING, 21 | ) 22 | 23 | try: 24 | from jinja2 import FileSystemLoader, Environment 25 | except ImportError: 26 | from charmhelpers.fetch import apt_install 27 | from charmhelpers.fetch import apt_update 28 | apt_update(fatal=True) 29 | apt_install('python3-jinja2', fatal=True) 30 | from jinja2 import FileSystemLoader, Environment 31 | 32 | 33 | # NOTE: function separated from main rendering code to facilitate easier 34 | # mocking in unit tests. 35 | def write(path, data): 36 | with open(path, 'wb') as out: 37 | out.write(data) 38 | 39 | 40 | def get_template_path(template_dir, path): 41 | """Returns the template file which would be used to render the path. 42 | 43 | The path to the template file is returned. 44 | :param template_dir: the directory the templates are located in 45 | :param path: the file path to be written to. 46 | :returns: path to the template file 47 | """ 48 | return os.path.join(template_dir, os.path.basename(path)) 49 | 50 | 51 | def render_and_write(template_dir, path, context): 52 | """Renders the specified template into the file. 53 | 54 | :param template_dir: the directory to load the template from 55 | :param path: the path to write the templated contents to 56 | :param context: the parameters to pass to the rendering engine 57 | """ 58 | env = Environment(loader=FileSystemLoader(template_dir)) 59 | template_file = os.path.basename(path) 60 | template = env.get_template(template_file) 61 | log('Rendering from template: %s' % template.name, level=DEBUG) 62 | rendered_content = template.render(context) 63 | if not rendered_content: 64 | log("Render returned None - skipping '%s'" % path, 65 | level=WARNING) 66 | return 67 | 68 | write(path, rendered_content.encode('utf-8').strip()) 69 | log('Wrote template %s' % path, level=DEBUG) 70 | -------------------------------------------------------------------------------- /hooks/charmhelpers/core/sysctl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright 2014-2015 Canonical Limited. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | import yaml 19 | 20 | from subprocess import check_call, CalledProcessError 21 | 22 | from charmhelpers.core.hookenv import ( 23 | log, 24 | DEBUG, 25 | ERROR, 26 | WARNING, 27 | ) 28 | 29 | from charmhelpers.core.host import is_container 30 | 31 | __author__ = 'Jorge Niedbalski R. ' 32 | 33 | 34 | def create(sysctl_dict, sysctl_file, ignore=False): 35 | """Creates a sysctl.conf file from a YAML associative array 36 | 37 | :param sysctl_dict: a dict or YAML-formatted string of sysctl 38 | options eg "{ 'kernel.max_pid': 1337 }" 39 | :type sysctl_dict: str 40 | :param sysctl_file: path to the sysctl file to be saved 41 | :type sysctl_file: str or unicode 42 | :param ignore: If True, ignore "unknown variable" errors. 43 | :type ignore: bool 44 | :returns: None 45 | """ 46 | if type(sysctl_dict) is not dict: 47 | try: 48 | sysctl_dict_parsed = yaml.safe_load(sysctl_dict) 49 | except yaml.YAMLError: 50 | log("Error parsing YAML sysctl_dict: {}".format(sysctl_dict), 51 | level=ERROR) 52 | return 53 | else: 54 | sysctl_dict_parsed = sysctl_dict 55 | 56 | with open(sysctl_file, "w") as fd: 57 | for key, value in sysctl_dict_parsed.items(): 58 | fd.write("{}={}\n".format(key, value)) 59 | 60 | log("Updating sysctl_file: {} values: {}".format(sysctl_file, 61 | sysctl_dict_parsed), 62 | level=DEBUG) 63 | 64 | call = ["sysctl", "-p", sysctl_file] 65 | if ignore: 66 | call.append("-e") 67 | 68 | try: 69 | check_call(call) 70 | except CalledProcessError as e: 71 | if is_container(): 72 | log("Error setting some sysctl keys in this container: {}".format(e.output), 73 | level=WARNING) 74 | else: 75 | raise e 76 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/host/checks/login.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from charmhelpers.contrib.hardening.audits.file import TemplatedFile 16 | from charmhelpers.contrib.hardening.host import TEMPLATES_DIR 17 | from charmhelpers.contrib.hardening import utils 18 | 19 | 20 | def get_audits(): 21 | """Get OS hardening login.defs audits. 22 | 23 | :returns: dictionary of audits 24 | """ 25 | audits = [TemplatedFile('/etc/login.defs', LoginContext(), 26 | template_dir=TEMPLATES_DIR, 27 | user='root', group='root', mode=0o0444)] 28 | return audits 29 | 30 | 31 | class LoginContext(object): 32 | 33 | def __call__(self): 34 | settings = utils.get_settings('os') 35 | 36 | # Octal numbers in yaml end up being turned into decimal, 37 | # so check if the umask is entered as a string (e.g. '027') 38 | # or as an octal umask as we know it (e.g. 002). If its not 39 | # a string assume it to be octal and turn it into an octal 40 | # string. 41 | umask = settings['environment']['umask'] 42 | if not isinstance(umask, str): 43 | umask = '%s' % oct(umask) 44 | 45 | ctxt = { 46 | 'additional_user_paths': 47 | settings['environment']['extra_user_paths'], 48 | 'umask': umask, 49 | 'pwd_max_age': settings['auth']['pw_max_age'], 50 | 'pwd_min_age': settings['auth']['pw_min_age'], 51 | 'uid_min': settings['auth']['uid_min'], 52 | 'sys_uid_min': settings['auth']['sys_uid_min'], 53 | 'sys_uid_max': settings['auth']['sys_uid_max'], 54 | 'gid_min': settings['auth']['gid_min'], 55 | 'sys_gid_min': settings['auth']['sys_gid_min'], 56 | 'sys_gid_max': settings['auth']['sys_gid_max'], 57 | 'login_retries': settings['auth']['retries'], 58 | 'login_timeout': settings['auth']['timeout'], 59 | 'chfn_restrict': settings['auth']['chfn_restrict'], 60 | 'allow_login_without_home': settings['auth']['allow_homeless'] 61 | } 62 | 63 | return ctxt 64 | -------------------------------------------------------------------------------- /hooks/charmhelpers/fetch/giturl.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | from subprocess import check_output, CalledProcessError, STDOUT 17 | from charmhelpers.fetch import ( 18 | BaseFetchHandler, 19 | UnhandledSource, 20 | filter_installed_packages, 21 | install, 22 | ) 23 | 24 | if filter_installed_packages(['git']) != []: 25 | install(['git']) 26 | if filter_installed_packages(['git']) != []: 27 | raise NotImplementedError('Unable to install git') 28 | 29 | 30 | class GitUrlFetchHandler(BaseFetchHandler): 31 | """Handler for git branches via generic and github URLs.""" 32 | 33 | def can_handle(self, source): 34 | url_parts = self.parse_url(source) 35 | # TODO (mattyw) no support for ssh git@ yet 36 | if url_parts.scheme not in ('http', 'https', 'git', ''): 37 | return False 38 | elif not url_parts.scheme: 39 | return os.path.exists(os.path.join(source, '.git')) 40 | else: 41 | return True 42 | 43 | def clone(self, source, dest, branch="master", depth=None): 44 | if not self.can_handle(source): 45 | raise UnhandledSource("Cannot handle {}".format(source)) 46 | 47 | if os.path.exists(dest): 48 | cmd = ['git', '-C', dest, 'pull', source, branch] 49 | else: 50 | cmd = ['git', 'clone', source, dest, '--branch', branch] 51 | if depth: 52 | cmd.extend(['--depth', depth]) 53 | check_output(cmd, stderr=STDOUT) 54 | 55 | def install(self, source, branch="master", dest=None, depth=None): 56 | url_parts = self.parse_url(source) 57 | branch_name = url_parts.path.strip("/").split("/")[-1] 58 | if dest: 59 | dest_dir = os.path.join(dest, branch_name) 60 | else: 61 | dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", 62 | branch_name) 63 | try: 64 | self.clone(source, dest_dir, branch, depth) 65 | except CalledProcessError as e: 66 | raise UnhandledSource(e) 67 | except OSError as e: 68 | raise UnhandledSource(e.strerror) 69 | return dest_dir 70 | -------------------------------------------------------------------------------- /hooks/charmhelpers/fetch/bzrurl.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | from subprocess import STDOUT, check_output 17 | from charmhelpers.fetch import ( 18 | BaseFetchHandler, 19 | UnhandledSource, 20 | filter_installed_packages, 21 | install, 22 | ) 23 | from charmhelpers.core.host import mkdir 24 | 25 | 26 | if filter_installed_packages(['bzr']) != []: 27 | install(['bzr']) 28 | if filter_installed_packages(['bzr']) != []: 29 | raise NotImplementedError('Unable to install bzr') 30 | 31 | 32 | class BzrUrlFetchHandler(BaseFetchHandler): 33 | """Handler for bazaar branches via generic and lp URLs.""" 34 | 35 | def can_handle(self, source): 36 | url_parts = self.parse_url(source) 37 | if url_parts.scheme not in ('bzr+ssh', 'lp', ''): 38 | return False 39 | elif not url_parts.scheme: 40 | return os.path.exists(os.path.join(source, '.bzr')) 41 | else: 42 | return True 43 | 44 | def branch(self, source, dest, revno=None): 45 | if not self.can_handle(source): 46 | raise UnhandledSource("Cannot handle {}".format(source)) 47 | cmd_opts = [] 48 | if revno: 49 | cmd_opts += ['-r', str(revno)] 50 | if os.path.exists(dest): 51 | cmd = ['bzr', 'pull'] 52 | cmd += cmd_opts 53 | cmd += ['--overwrite', '-d', dest, source] 54 | else: 55 | cmd = ['bzr', 'branch'] 56 | cmd += cmd_opts 57 | cmd += [source, dest] 58 | check_output(cmd, stderr=STDOUT) 59 | 60 | def install(self, source, dest=None, revno=None): 61 | url_parts = self.parse_url(source) 62 | branch_name = url_parts.path.strip("/").split("/")[-1] 63 | if dest: 64 | dest_dir = os.path.join(dest, branch_name) 65 | else: 66 | dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", 67 | branch_name) 68 | 69 | if dest and not os.path.exists(dest): 70 | mkdir(dest, perms=0o755) 71 | 72 | try: 73 | self.branch(source, dest_dir, revno) 74 | except OSError as e: 75 | raise UnhandledSource(e.strerror) 76 | return dest_dir 77 | -------------------------------------------------------------------------------- /hooks/charmhelpers/core/hugepage.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright 2014-2015 Canonical Limited. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import yaml 18 | from charmhelpers.core import fstab 19 | from charmhelpers.core import sysctl 20 | from charmhelpers.core.host import ( 21 | add_group, 22 | add_user_to_group, 23 | fstab_mount, 24 | mkdir, 25 | ) 26 | from charmhelpers.core.strutils import bytes_from_string 27 | from subprocess import check_output 28 | 29 | 30 | def hugepage_support(user, group='hugetlb', nr_hugepages=256, 31 | max_map_count=65536, mnt_point='/run/hugepages/kvm', 32 | pagesize='2MB', mount=True, set_shmmax=False): 33 | """Enable hugepages on system. 34 | 35 | Args: 36 | user (str) -- Username to allow access to hugepages to 37 | group (str) -- Group name to own hugepages 38 | nr_hugepages (int) -- Number of pages to reserve 39 | max_map_count (int) -- Number of Virtual Memory Areas a process can own 40 | mnt_point (str) -- Directory to mount hugepages on 41 | pagesize (str) -- Size of hugepages 42 | mount (bool) -- Whether to Mount hugepages 43 | """ 44 | group_info = add_group(group) 45 | gid = group_info.gr_gid 46 | add_user_to_group(user, group) 47 | if max_map_count < 2 * nr_hugepages: 48 | max_map_count = 2 * nr_hugepages 49 | sysctl_settings = { 50 | 'vm.nr_hugepages': nr_hugepages, 51 | 'vm.max_map_count': max_map_count, 52 | 'vm.hugetlb_shm_group': gid, 53 | } 54 | if set_shmmax: 55 | shmmax_current = int(check_output(['sysctl', '-n', 'kernel.shmmax'])) 56 | shmmax_minsize = bytes_from_string(pagesize) * nr_hugepages 57 | if shmmax_minsize > shmmax_current: 58 | sysctl_settings['kernel.shmmax'] = shmmax_minsize 59 | sysctl.create(yaml.dump(sysctl_settings), '/etc/sysctl.d/10-hugepage.conf') 60 | mkdir(mnt_point, owner='root', group='root', perms=0o755, force=False) 61 | lfstab = fstab.Fstab() 62 | fstab_entry = lfstab.get_entry_by_attr('mountpoint', mnt_point) 63 | if fstab_entry: 64 | lfstab.remove_entry(fstab_entry) 65 | entry = lfstab.Entry('nodev', mnt_point, 'hugetlbfs', 66 | 'mode=1770,gid={},pagesize={}'.format(gid, pagesize), 0, 0) 67 | lfstab.add_entry(entry) 68 | if mount: 69 | fstab_mount(mnt_point) 70 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/storage/linux/loopback.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import re 17 | from subprocess import ( 18 | check_call, 19 | check_output, 20 | ) 21 | 22 | 23 | ################################################## 24 | # loopback device helpers. 25 | ################################################## 26 | def loopback_devices(): 27 | ''' 28 | Parse through 'losetup -a' output to determine currently mapped 29 | loopback devices. Output is expected to look like: 30 | 31 | /dev/loop0: [0807]:961814 (/tmp/my.img) 32 | 33 | or: 34 | 35 | /dev/loop0: [0807]:961814 (/tmp/my.img (deleted)) 36 | 37 | :returns: dict: a dict mapping {loopback_dev: backing_file} 38 | ''' 39 | loopbacks = {} 40 | cmd = ['losetup', '-a'] 41 | output = check_output(cmd).decode('utf-8') 42 | devs = [d.strip().split(' ', 2) for d in output.splitlines() if d != ''] 43 | for dev, _, f in devs: 44 | loopbacks[dev.replace(':', '')] = re.search(r'\((.+)\)', f).groups()[0] 45 | return loopbacks 46 | 47 | 48 | def create_loopback(file_path): 49 | ''' 50 | Create a loopback device for a given backing file. 51 | 52 | :returns: str: Full path to new loopback device (eg, /dev/loop0) 53 | ''' 54 | file_path = os.path.abspath(file_path) 55 | check_call(['losetup', '--find', file_path]) 56 | for d, f in loopback_devices().items(): 57 | if f == file_path: 58 | return d 59 | 60 | 61 | def ensure_loopback_device(path, size): 62 | ''' 63 | Ensure a loopback device exists for a given backing file path and size. 64 | If it a loopback device is not mapped to file, a new one will be created. 65 | 66 | TODO: Confirm size of found loopback device. 67 | 68 | :returns: str: Full path to the ensured loopback device (eg, /dev/loop0) 69 | ''' 70 | for d, f in loopback_devices().items(): 71 | if f == path: 72 | return d 73 | 74 | if not os.path.exists(path): 75 | cmd = ['truncate', '--size', size, path] 76 | check_call(cmd) 77 | 78 | return create_loopback(path) 79 | 80 | 81 | def is_mapped_loopback_device(device): 82 | """ 83 | Checks if a given device name is an existing/mapped loopback device. 84 | :param device: str: Full path to the device (eg, /dev/loop1). 85 | :returns: str: Path to the backing file if is a loopback device 86 | empty string otherwise 87 | """ 88 | return loopback_devices().get(device, "") 89 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hahelpers/apache.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2015 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # 16 | # Copyright 2012 Canonical Ltd. 17 | # 18 | # This file is sourced from lp:openstack-charm-helpers 19 | # 20 | # Authors: 21 | # James Page 22 | # Adam Gandelman 23 | # 24 | 25 | import os 26 | 27 | from charmhelpers.core import host 28 | from charmhelpers.core.hookenv import ( 29 | config as config_get, 30 | relation_get, 31 | relation_ids, 32 | related_units as relation_list, 33 | log, 34 | INFO, 35 | ) 36 | 37 | # This file contains the CA cert from the charms ssl_ca configuration 38 | # option, in future the file name should be updated reflect that. 39 | CONFIG_CA_CERT_FILE = 'keystone_juju_ca_cert' 40 | 41 | 42 | def get_cert(cn=None): 43 | # TODO: deal with multiple https endpoints via charm config 44 | cert = config_get('ssl_cert') 45 | key = config_get('ssl_key') 46 | if not (cert and key): 47 | log("Inspecting identity-service relations for SSL certificate.", 48 | level=INFO) 49 | cert = key = None 50 | if cn: 51 | ssl_cert_attr = 'ssl_cert_{}'.format(cn) 52 | ssl_key_attr = 'ssl_key_{}'.format(cn) 53 | else: 54 | ssl_cert_attr = 'ssl_cert' 55 | ssl_key_attr = 'ssl_key' 56 | for r_id in relation_ids('identity-service'): 57 | for unit in relation_list(r_id): 58 | if not cert: 59 | cert = relation_get(ssl_cert_attr, 60 | rid=r_id, unit=unit) 61 | if not key: 62 | key = relation_get(ssl_key_attr, 63 | rid=r_id, unit=unit) 64 | return (cert, key) 65 | 66 | 67 | def get_ca_cert(): 68 | ca_cert = config_get('ssl_ca') 69 | if ca_cert is None: 70 | log("Inspecting identity-service relations for CA SSL certificate.", 71 | level=INFO) 72 | for r_id in (relation_ids('identity-service') + 73 | relation_ids('identity-credentials')): 74 | for unit in relation_list(r_id): 75 | if ca_cert is None: 76 | ca_cert = relation_get('ca_cert', 77 | rid=r_id, unit=unit) 78 | return ca_cert 79 | 80 | 81 | def retrieve_ca_cert(cert_file): 82 | cert = None 83 | if os.path.isfile(cert_file): 84 | with open(cert_file, 'rb') as crt: 85 | cert = crt.read() 86 | return cert 87 | 88 | 89 | def install_ca_cert(ca_cert): 90 | host.install_ca_cert(ca_cert, CONFIG_CA_CERT_FILE) 91 | -------------------------------------------------------------------------------- /hooks/charmhelpers/contrib/hardening/mysql/checks/config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Canonical Limited. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import subprocess 16 | 17 | from charmhelpers.core.hookenv import ( 18 | log, 19 | WARNING, 20 | ) 21 | from charmhelpers.contrib.hardening.audits.file import ( 22 | FilePermissionAudit, 23 | DirectoryPermissionAudit, 24 | TemplatedFile, 25 | ) 26 | from charmhelpers.contrib.hardening.mysql import TEMPLATES_DIR 27 | from charmhelpers.contrib.hardening import utils 28 | 29 | 30 | def get_audits(): 31 | """Get MySQL hardening config audits. 32 | 33 | :returns: dictionary of audits 34 | """ 35 | if subprocess.call(['which', 'mysql'], stdout=subprocess.PIPE) != 0: 36 | log("MySQL does not appear to be installed on this node - " 37 | "skipping mysql hardening", level=WARNING) 38 | return [] 39 | 40 | settings = utils.get_settings('mysql') 41 | hardening_settings = settings['hardening'] 42 | my_cnf = hardening_settings['mysql-conf'] 43 | 44 | audits = [ 45 | FilePermissionAudit(paths=[my_cnf], user='root', 46 | group='root', mode=0o0600), 47 | 48 | TemplatedFile(hardening_settings['hardening-conf'], 49 | MySQLConfContext(), 50 | TEMPLATES_DIR, 51 | mode=0o0750, 52 | user='mysql', 53 | group='root', 54 | service_actions=[{'service': 'mysql', 55 | 'actions': ['restart']}]), 56 | 57 | # MySQL and Percona charms do not allow configuration of the 58 | # data directory, so use the default. 59 | DirectoryPermissionAudit('/var/lib/mysql', 60 | user='mysql', 61 | group='mysql', 62 | recursive=False, 63 | mode=0o755), 64 | 65 | DirectoryPermissionAudit('/etc/mysql', 66 | user='root', 67 | group='root', 68 | recursive=False, 69 | mode=0o700), 70 | ] 71 | 72 | return audits 73 | 74 | 75 | class MySQLConfContext(object): 76 | """Defines the set of key/value pairs to set in a mysql config file. 77 | 78 | This context, when called, will return a dictionary containing the 79 | key/value pairs of setting to specify in the 80 | /etc/mysql/conf.d/hardening.cnf file. 81 | """ 82 | def __call__(self): 83 | settings = utils.get_settings('mysql') 84 | return { 85 | 'mysql_settings': [(k, v) for k, v in settings['security'].items()] 86 | } 87 | --------------------------------------------------------------------------------