This is a set of modules to allow you to configure pfSense firewalls with ansible.
This is now maintained as an ansible collection at https://github.com/pfsensible/core
GPLv3.0 or later
Ansible modules for managing pfSense firewalls
License: GNU General Public License v3.0
This is a set of modules to allow you to configure pfSense firewalls with ansible.
This is now maintained as an ansible collection at https://github.com/pfsensible/core
GPLv3.0 or later
Hi,
I noticed that esp is not accepted as a protocol when creating a rule. When checking the code I saw that more existing protocols are also not accepted. Why aren't al available protocols accepted by the rule module?
Currently, there is support for CA's but we should also have a way of managing certificates.
Hi,
First of all I have to thank you for great tool to manage pfsense. I'm testing it now with adding users to my home pfsense. I have noticed that in web interface user is added right with password, sshkey and group, but it does not change /etc/group file. It affect for example users that have been added to admin group but they cannot run sudo. They finally appear in /etc/group if you edit any user with removing or adding him to the particular group.
Using:
pfsense: 2.4.5-RELEASE
ansible: 2.9.6
on ubuntu 20.04
Installed pfsensible from ansible galaxy using the command: ansible-galaxy collection install pfsensible.core
What I'm finding is that if I run the user module, where a user already exists, It's removing the user nicely. However, if I set a user to be removed and the user is already gone, the module errors.
Playbook with users there:
- hosts: all
gather_facts: false
vars:
users:
- name: s123456
pass: "test"
- name: s321456
pass: nextpass
removeusers:
- name: s123456
- name: s321456
tasks:
- name: Add users
pfsensible.core.user:
name: "{{ item.name }}"
password: "{{ item.pass| password_hash('bcrypt') }}"
#password: "{% if defined(item.pass) %}{{ item.pass | password_hash('bcrypt') }}{% endif %}"
loop: "{{ users }}"
- name: Remove users
pfsensible.core.user:
name: "{{ item.name }}"
state: absent
loop: "{{ removeusers }}"
run log:
~/g/c/pfsense> ansible-playbook -i inventory.ini provision_pfsense_users.yml
PLAY [all] *********************************************************************************************
TASK [Add users] ***************************************************************************************
changed: [pf1] => (item={'name': 's123456', 'pass': 'test'})
changed: [pf1] => (item={'name': 's321456', 'pass': 'nextpass'})
[WARNING]: Platform freebsd on host pf1 is using the discovered Python interpreter at
/usr/local/bin/python3.7, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more
information.
TASK [Remove users] ************************************************************************************
changed: [pf1] => (item={'name': 's123456'})
changed: [pf1] => (item={'name': 's321456'})
PLAY RECAP *********************************************************************************************
pf1 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
~/g/c/pfsense>
However, this playbook:
- hosts: all
gather_facts: false
vars:
users:
- name: s123456
pass: "test"
- name: s321456
pass: nextpass
removeusers:
- name: gonealready
tasks:
- name: Add users
pfsensible.core.user:
name: "{{ item.name }}"
password: "{{ item.pass| password_hash('bcrypt') }}"
#password: "{% if defined(item.pass) %}{{ item.pass | password_hash('bcrypt') }}{% endif %}"
loop: "{{ users }}"
- name: Remove users
pfsensible.core.user:
name: "{{ item.name }}"
state: absent
loop: "{{ removeusers }}"
runs like this:
~/g/c/pfsense> ansible-playbook -i inventory.ini provision_pfsense_users.yml
PLAY [all] *********************************************************************************************
TASK [Add users] ***************************************************************************************
changed: [pf1] => (item={'name': 's123456', 'pass': 'test'})
changed: [pf1] => (item={'name': 's321456', 'pass': 'nextpass'})
[WARNING]: Platform freebsd on host pf1 is using the discovered Python interpreter at
/usr/local/bin/python3.7, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more
information.
TASK [Remove users] ************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'NoneType' object has no attribute 'find'
failed: [pf1] (item={'name': 'gonealready'}) => {"ansible_loop_var": "item", "changed": false, "item": {"name": "gonealready"}, "module_stderr": "Shared connection to 138.80.128.139 closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File \"/root/.ansible/tmp/ansible-tmp-1591917213.9751663-85254998345163/AnsiballZ_user.py\", line 102, in <module>\r\n _ansiballz_main()\r\n File \"/root/.ansible/tmp/ansible-tmp-1591917213.9751663-85254998345163/AnsiballZ_user.py\", line 94, in _ansiballz_main\r\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n File \"/root/.ansible/tmp/ansible-tmp-1591917213.9751663-85254998345163/AnsiballZ_user.py\", line 40, in invoke_module\r\n runpy.run_module(mod_name='ansible_collections.pfsensible.core.plugins.modules.user', init_globals=None, run_name='__main__', alter_sys=True)\r\n File \"/usr/local/lib/python3.7/runpy.py\", line 205, in run_module\r\n return _run_module_code(code, init_globals, run_name, mod_spec)\r\n File \"/usr/local/lib/python3.7/runpy.py\", line 96, in _run_module_code\r\n mod_name, mod_spec, pkg_name, script_name)\r\n File \"/usr/local/lib/python3.7/runpy.py\", line 85, in _run_code\r\n exec(code, run_globals)\r\n File \"/tmp/ansible_pfsensible.core.user_payload_sa82xwau/ansible_pfsensible.core.user_payload.zip/ansible_collections/pfsensible/core/plugins/modules/user.py\", line 345, in <module>\r\n File \"/tmp/ansible_pfsensible.core.user_payload_sa82xwau/ansible_pfsensible.core.user_payload.zip/ansible_collections/pfsensible/core/plugins/modules/user.py\", line 336, in main\r\n File \"/tmp/ansible_pfsensible.core.user_payload_sa82xwau/ansible_pfsensible.core.user_payload.zip/ansible_collections/pfsensible/core/plugins/modules/user.py\", line 277, in remove\r\nAttributeError: 'NoneType' object has no attribute 'find'\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
PLAY RECAP *********************************************************************************************
pf1 : ok=1 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
It's not a big deal as the user is gone, as mentioned, but thought you would like to know of the bug.
I wrote a playbook with this repo from the beginning of december that used the pfsense_interface
and pfsense_rule
modules and it worked great. I wanted to use the new nat rules module so I pulled the updates for the repo and copied it in to ...site-packages/ansible/module_utils/network/pfsense
like I had before, but now the pfsense_interface
module fails with...
"msg": "New-style module did not handle its own exit"
I tried updating ansible to the most recent version to no avail. I'm not sure if the refactoring that was done mid-december might have affected its functionality.
Hello, I have some problems with using this module in my environment.
failed: [] (item={u'address': u'172.16.10.145 172.16.10.111', u'type': u'host', u'name': u'adservers', u'descr': u'Active Directory Servers', u'detail': u'ad1||ad2'}) => {"changed": false, "item": {"address": "172.16.10.145 172.16.10.111", "descr": "Active Directory Servers", "detail": "ad1||ad2", "name": "adservers", "type": "host"}, "module_stderr": "Shared connection to closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File \"/home/dneichev/.ansible/tmp/ansible-tmp-1552989321.67-99305010884620/AnsiballZ_pfsense_alias.py\", line 113, in <module>\r\n _ansiballz_main()\r\n File \"/home/dneichev/.ansible/tmp/ansible-tmp-1552989321.67-99305010884620/AnsiballZ_pfsense_alias.py\", line 105, in _ansiballz_main\r\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n File \"/home/dneichev/.ansible/tmp/ansible-tmp-1552989321.67-99305010884620/AnsiballZ_pfsense_alias.py\", line 48, in invoke_module\r\n imp.load_module('__main__', mod, module, MOD_DESC)\r\n File \"/tmp/ansible_pfsense_alias_payload_P6d4X3/__main__.py\", line 93, in <module>\r\n File \"/tmp/ansible_pfsense_alias_payload_P6d4X3/__main__.py\", line 89, in main\r\n File \"/tmp/ansible_pfsense_alias_payload_P6d4X3/ansible_pfsense_alias_payload.zip/ansible/module_utils/networking/pfsense/pfsense_alias.py\", line 178, in commit_changes\r\n File \"/tmp/ansible_pfsense_alias_payload_P6d4X3/ansible_pfsense_alias_payload.zip/ansible/module_utils/networking/pfsense/pfsense.py\", line 403, in write_config\r\n File \"/usr/local/lib/python2.7/shutil.py\", line 316, in move\r\n copy2(src, real_dst)\r\n File \"/usr/local/lib/python2.7/shutil.py\", line 145, in copy2\r\n copystat(src, dst)\r\n File \"/usr/local/lib/python2.7/shutil.py\", line 112, in copystat\r\n os.utime(dst, (st.st_atime, st.st_mtime))\r\nOSError: [Errno 1] Operation not permitted: '/cf/conf/config.xml'\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
Can you help me to solve this problem?
I don't modificate any of ansible files and try to check how this module works.
If I add a new rule, e.g.:
- name: "Add force proxy rule"
pfsense_rule:
name: "Force proxy for some hosts"
action: block
interface: lan
ipprotocol: inet
protocol: tcp
source: "force_proxy"
destination: "any:web_ports"
before: "Allow http"
log: yes
tracker: "0100002000"
state: present
It gets added in a disabled state.
I haven't been able to figure out how to set NAT firewall rules. Is this possible with the plugin?
I was previously using this module with ansible 2.7 and since I upgraded to ansible 2.9 I tried to use it as an ansible collection but I cannot get it working. I am not sure what I am doing wrong.
I am using ansible-2.9.2
with python-2.7.5
in a centos7
machine
This is my requirements file for the playbook:
$ cat collections.yml
---
collections:
- name: pfsensible.core
#version: 0.1.0
#source: https://galaxy.ansible.com
I installed the collection like this:
ansible-galaxy collection install -r collections.yml -p ./collections
Process install dependency map
Starting collection install process
Installing 'pfsensible.core:0.1.0' to '/home/escobar/ansible/playbooks/ansible-playbook-firewall-biomedit/collections/ansible_collections/pfsensible/core'
then I added an ansible.cfg
file as suggested in the README
$ cat ansible.cfg
[defaults]
collections_paths = collections
$ ansible-config dump --only-changed
COLLECTIONS_PATHS(/home/escobar/ansible/playbooks/ansible-playbook-firewall-biomedit/ansible.cfg) = [u'/home/escobar/ansible/playbooks/ansible-playbook-firewall-biomedit/collections']
so in the root folder of my playbook I have these files:
$> ls -1
ansible.cfg
collections/
collections.yml
inventory
test-playbook.yml
this is what I have in the collections
folder
$ tree -d -L 4 collections
collections
βββ ansible_collections
βββ pfsensible
βββ core
βββ examples
βββ misc
βββ plugins
βββ tests
7 directories
but when I try to run this playbook:
$> cat test-playbook.yml
---
- hosts: all
collections:
- pfsensible.core
tasks:
- name: Add adservers alias
pfsense_alias:
name: adservers
address: 10.0.0.1 10.0.0.2
state: present
The ansible modules that should be provided by the collection are not found:
$> ansible-playbook test-playbook.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
ERROR! couldn't resolve module/action 'pfsense_alias'. This often indicates a misspelling, missing collection, or incorrect module path.
The error appears to be in '/home/escobar/ansible/playbooks/ansible-playbook-firewall-biomedit/test-playbook.yml': line 9, column 7, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Add adservers alias
^ here
Is this a problem with the collection or am I doing something wrong?
Admin Access / webConfigurator / SSL Certificate Assignment
Admin Access / webConfigurator / Anti-Lockout
Admin Access / webConfigurator / DNS Rebind Check
Admin Access / webConfigurator / Disable HTTP_REFERER
Admin Access / Secure Shell / SSHd Key Only
Admin Access / Secure Shell / SSH Port
Admin Access / Login Protection / Whitelist
Networking / IPv6 Options / Allow IPv6
Networking / IPv6 Options / Prefer IPv4 over IPv6
Networking / Network Interfaces / Hardware Checksum Offloading
We deploy on physical and virtual machines, VMs require this to be checked (true)
Miscellaneous / Cryptographic & Thermal Hardware / Cryptographic Hardware
Notifications / E-Mail / * All Fields *
Hi, these modules have been extremely helpful. I would love to see virtual IP management and 1:1 NAT rule management.
Regards
Russell.
Hi. Sorry but I'm unable to make it work as described on my test pfsense 2.4.4.
Maybe I'm missing something. I've tried to create user with simple pfsense_user playbook
- hosts: "{{ hostitem }}"
gather_facts: False
become: yes
# connection: paramiko
tasks:
- name: Add operator user
pfsense_user:
name: operator
descr: Operator
scope: user
groupname: Operators
priv: [ 'page-all', 'user-shell-access' ]
But even with paramiko connection the error is always like this:
...
Bad -c option
debug3: mux_client_read_packet: read header failed: Broken pipe
debug2: Received exit status from master 2
fatal: [pfsense_test]: UNREACHABLE! => {
"changed": false,
"msg": "Authentication or permission failure. In some cases, you may have been able to authenticate and did not have permissions on the target directory. Consider changing the remote tmp path in ansible.cfg to a path rooted in \"/tmp\". Failed command was: ( umask 77 && mkdir -p \"` echo ~/.ansible/tmp/ansible-tmp-1576870605.3-68562282288037 `\" && echo ansible-tmp-1576870605.3-68562282288037=\"` echo ~/.ansible/tmp/ansible-tmp-1576870605.3-68562282288037 `\" ), exited with result 2, stderr output: OpenSSH_7.6p1 Ubuntu-4ubuntu0.3, OpenSSL 1.0.2n 7 Dec 2017\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/ssh_config line 19: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug2: mux_client_hello_exchange: master version 4\r\ndebug3: mux_client_forwards: request forwardings: 0 local, 0 remote\r\ndebug3: mux_client_request_session: entering\r\ndebug3: mux_client_request_alive: entering\r\ndebug3: mux_client_request_alive: done pid = 22716\r\ndebug3: mux_client_request_session: session request sent\r\ndebug1: mux_client_request_session: master session id: 2\r\nBad -c option\ndebug3: mux_client_read_packet: read header failed: Broken pipe\r\ndebug2: Received exit status from master 2\r\n",
"unreachable": true
}
to retry, use: --limit @/etc/ansible/roles/ansible-pfsense-github/test-user-add.retry
PLAY RECAP *****************************************************************************************************************************************************************************************************
pfsense_test : ok=0 changed=0 unreachable=1 failed=0
My ansible version:
root@COMP-01:/etc/ansible/roles/ansible-pfsense-github# ansible --version
ansible 2.7.15
config file = /etc/ansible/roles/ansible-pfsense-github/ansible.cfg
configured module search path = [u'/etc/ansible/roles/library']
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.15+ (default, Oct 7 2019, 17:39:04) [GCC 7.4.0]
Even ansible ping command is not working..
root@COMP-01:/etc/ansible/roles/ansible-pfsense-github# ansible -m ping -i hosts pfsense_test -c paramiko --ask-pass -b -vvvvv
ansible 2.7.15
config file = /etc/ansible/roles/ansible-pfsense-github/ansible.cfg
configured module search path = [u'/etc/ansible/roles/library']
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.15+ (default, Oct 7 2019, 17:39:04) [GCC 7.4.0]
Using /etc/ansible/roles/ansible-pfsense-github/ansible.cfg as config file
SSH password:
setting up inventory plugins
/etc/ansible/roles/ansible-pfsense-github/hosts did not meet host_list requirements, check plugin documentation if this is unexpected
/etc/ansible/roles/ansible-pfsense-github/hosts did not meet script requirements, check plugin documentation if this is unexpected
Parsed /etc/ansible/roles/ansible-pfsense-github/hosts inventory source with ini plugin
Loading callback plugin minimal of type stdout, v2.0 from /usr/lib/python2.7/dist-packages/ansible/plugins/callback/minimal.pyc
META: ran handlers
<172.254.29.254> ESTABLISH PARAMIKO SSH CONNECTION FOR USER: admin on PORT 22 TO 172.254.29.254
<172.254.29.254> EXEC /bin/sh -c 'echo ~admin && sleep 0'
<172.254.29.254> EXEC /bin/sh -c 'echo "`pwd`" && sleep 0'
<172.254.29.254> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo ~/.ansible/tmp/ansible-tmp-1577442259.16-60629702648004 `" && echo ansible-tmp-1577442259.16-60629702648004="` echo ~/.ansible/tmp/ansible-tmp-1577442259.16-60629702648004 `" ) && sleep 0'
pfsense_test | UNREACHABLE! => {
"changed": false,
"msg": "Authentication or permission failure. In some cases, you may have been able to authenticate and did not have permissions on the target directory. Consider changing the remote tmp path in ansible.cfg to a path rooted in \"/tmp\". Failed command was: ( umask 77 && mkdir -p \"` echo ~/.ansible/tmp/ansible-tmp-1577442259.16-60629702648004 `\" && echo ansible-tmp-1577442259.16-60629702648004=\"` echo ~/.ansible/tmp/ansible-tmp-1577442259.16-60629702648004 `\" ), exited with result 2, stderr output: Bad -c option\n",
"unreachable": true
}
pfsense nat port forward fails with the example given in the module's doc below as well as with parameters that fit my environment (changing the ports to 80
and the target to 10.0.0.50:80
).
- name: "Add NAT port forward traffic rule"
pfsense_nat_port_forward:
descr: 'ssh'
interface: wan
source: any
destination: any:22
target: 1.2.3.4:22
associated_rule: pass
state: present
The full traceback is:
Traceback (most recent call last):
File "/root/.ansible/tmp/ansible-tmp-1578519901.9509819-67012684930639/AnsiballZ_pfsense_nat_port_forward.py", line 102, in <module>
_ansiballz_main()
File "/root/.ansible/tmp/ansible-tmp-1578519901.9509819-67012684930639/AnsiballZ_pfsense_nat_port_forward.py", line 94, in _ansiballz_main
invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
File "/root/.ansible/tmp/ansible-tmp-1578519901.9509819-67012684930639/AnsiballZ_pfsense_nat_port_forward.py", line 40, in invoke_module
runpy.run_module(mod_name='ansible.modules.pfsense_nat_port_forward', init_globals=None, run_name='__main__', alter_sys=True)
File "/usr/local/lib/python2.7/runpy.py", line 188, in run_module
fname, loader, pkg_name)
File "/usr/local/lib/python2.7/runpy.py", line 82, in _run_module_code
mod_name, mod_fname, mod_loader, pkg_name)
File "/usr/local/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/tmp/ansible_pfsense_nat_port_forward_payload_nR4yGm/ansible_pfsense_nat_port_forward_payload.zip/ansible/modules/pfsense_nat_port_forward.py", line 137, in <module>
File "/tmp/ansible_pfsense_nat_port_forward_payload_nR4yGm/ansible_pfsense_nat_port_forward_payload.zip/ansible/modules/pfsense_nat_port_forward.py", line 132, in main
File "/tmp/ansible_pfsense_nat_port_forward_payload_nR4yGm/ansible_pfsense_nat_port_forward_payload.zip/ansible/module_utils/network/pfsense/pfsense_module_base.py", line 184, in run
File "/tmp/ansible_pfsense_nat_port_forward_payload_nR4yGm/ansible_pfsense_nat_port_forward_payload.zip/ansible/module_utils/network/pfsense/pfsense_nat_port_forward.py", line 210, in _find_target
TypeError: 'NoneType' object is not iterable
Hi,
Whenever I try to use the pfsense_rule_separator I get a "AttributeError: 'NoneType' object has no attribute 'find'" error. Tested in various ways (with rules, specifying the position, etc ...) and it only seems to trigger when you don't have any separators yet; if there are present, it works fine.
Playbook:
- name: Add rule separator pfsense_rule_separator: name: Test state: present interface: wan color: danger
Full error:
TASK [Add rule separator] *******************************************************************************************************************************************************************************************************************
fatal: [192.0.2.110]: FAILED! => changed=false
module_stderr: |-
Shared connection to 192.0.2.110 closed.
module_stdout: |-
Traceback (most recent call last):
File "/root/.ansible/tmp/ansible-tmp-1567431318.58-16278943694065/AnsiballZ_pfsense_rule_separator.py", line 114, in
_ansiballz_main()
File "/root/.ansible/tmp/ansible-tmp-1567431318.58-16278943694065/AnsiballZ_pfsense_rule_separator.py", line 106, in _ansiballz_main
invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
File "/root/.ansible/tmp/ansible-tmp-1567431318.58-16278943694065/AnsiballZ_pfsense_rule_separator.py", line 49, in invoke_module
imp.load_module('main', mod, module, MOD_DESC)
File "/tmp/ansible_pfsense_rule_separator_payload_N1xzOS/main.py", line 90, in
File "/tmp/ansible_pfsense_rule_separator_payload_N1xzOS/main.py", line 85, in main
File "/tmp/ansible_pfsense_rule_separator_payload_N1xzOS/ansible_pfsense_rule_separator_payload.zip/ansible/module_utils/network/pfsense/pfsense_rule_separator.py", line 213, in run
File "/tmp/ansible_pfsense_rule_separator_payload_N1xzOS/ansible_pfsense_rule_separator_payload.zip/ansible/module_utils/network/pfsense/pfsense_rule_separator.py", line 145, in _add
File "/tmp/ansible_pfsense_rule_separator_payload_N1xzOS/ansible_pfsense_rule_separator_payload.zip/ansible/module_utils/network/pfsense/pfsense_rule_separator.py", line 122, in _get_expected_separator_position
File "/tmp/ansible_pfsense_rule_separator_payload_N1xzOS/ansible_pfsense_rule_separator_payload.zip/ansible/module_utils/network/pfsense/pfsense_rule_separator.py", line 106, in _get_separator_position
File "/tmp/ansible_pfsense_rule_separator_payload_N1xzOS/ansible_pfsense_rule_separator_payload.zip/ansible/module_utils/network/pfsense/pfsense_rule_separator.py", line 79, in _find_separator
AttributeError: 'NoneType' object has no attribute 'find'
msg: |-
MODULE FAILURE
See stdout/stderr for the exact error
rc: 1
I'd like to see a new feature/(module?) for configuring the Host Overrides for Unbound DNS resolver.
because pfsense does not have a python installed by default, even trying to run shell module would give a failure.
I think we need to find a way to deal with this issue in order to make it possible to use common ansible modules.
We now get warnings of usage of write_config() without a description. Should probably add what cert is added/updated/removed in the call.
ansible-pfsense/library/pfsense_ca.py
Line 248 in 7a2aa38
Hi - I'm the author of https://github.com/ndejong/pfsense_fauxapi and also an avid user of Ansible so I do like your approach.
I wonder if there is a way we could (or should) integrate or co-operate? It might make sense for example for FauxAPI to make it easy for ansible-pfsense to call FauxAPI directly (eg named pipe over ssh) thereby opening up all the FauxAPI function calls to ansible-pfsense.
Feel free to get in contact.
Hello,
The link to pfsense_file isn't correct, actually it's pointing to "https://github.com/opoplawski/ansible-pfsense/wiki/pfsense_ca"
Not sure what is the correct value because this module doesn't appear in the wiki page list.
Regards
@f-bor - We have a bit of an issue with the aggregate module's docs and argument specs:
13:46 ERROR: lib/ansible/modules/network/pfsense/pfsense_aggregate.py:0:0: doc-required-mismatch: Argument 'action' in argument_spec found in aggregated_rules is not required, but is documented as being required (75%)
13:46 ERROR: lib/ansible/modules/network/pfsense/pfsense_aggregate.py:0:0: doc-required-mismatch: Argument 'destination' in argument_spec found in aggregated_rules is not required, but is documented as being required (75%)
13:46 ERROR: lib/ansible/modules/network/pfsense/pfsense_aggregate.py:0:0: doc-required-mismatch: Argument 'enable' in argument_spec found in aggregated_interfaces is not required, but is documented as being required (75%)
13:46 ERROR: lib/ansible/modules/network/pfsense/pfsense_aggregate.py:0:0: doc-required-mismatch: Argument 'interface' in argument_spec found in aggregated_interfaces is not required, but is documented as being required (75%)
13:46 ERROR: lib/ansible/modules/network/pfsense/pfsense_aggregate.py:0:0: doc-required-mismatch: Argument 'interface' in argument_spec found in aggregated_rule_separators is not required, but is documented as being required (75%)
13:46 ERROR: lib/ansible/modules/network/pfsense/pfsense_aggregate.py:0:0: doc-required-mismatch: Argument 'source' in argument_spec found in aggregated_rules is not required, but is documented as being required (75%)
13:46 ERROR: lib/ansible/modules/network/pfsense/pfsense_aggregate.py:0:0: doc-required-mismatch: Argument 'state' in argument_spec found in aggregated_aliases is not required, but is documented as being required (75%)
13:46 ERROR: lib/ansible/modules/network/pfsense/pfsense_aggregate.py:0:0: doc-required-mismatch: Argument 'state' in argument_spec found in aggregated_interfaces is not required, but is documented as being required (75%)
13:46 ERROR: lib/ansible/modules/network/pfsense/pfsense_aggregate.py:0:0: doc-required-mismatch: Argument 'state' in argument_spec found in aggregated_rule_separators is not required, but is documented as being required (75%)
13:46 ERROR: lib/ansible/modules/network/pfsense/pfsense_aggregate.py:0:0: doc-required-mismatch: Argument 'state' in argument_spec found in aggregated_vlans is not required, but is documented as being required (75%)
This issue is that the individual modules allow for a "removal" (state: absent) mode - and so many arguments are optional, while in the aggregate module all items are in the "add" (state: present) mode. I'm not sure what the best way to handle this as it is nice to be able to re-use as much of the argument specs as possible.
Hello,
Do you think it would be possible to add modules pfsense-openvpn server and client?
Hello,
Sorry to bother again, I have some trouble with CA setup.
I use the following playbook:
- name: Setup certs
pfsense_ca:
name: "{{ item.name }}"
certificate: "{{ item.certificate }}"
state: present
with_items:
- "{{ pfsense_ca }}"
I tried this variable file:
pfsense_ca:
- name: Torque CA
certificate: |
-----BEGIN CERTIFICATE-----
MIIFhTCCA22gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwUzELMAkGA1UEBhMCRlIx
DzANBgNVBAgMBkZyYW5jZTEOMAwGA1UEBwwFUGFyaXMxDzANBgNVBAoMBlRvcnF1
ZTESMBAGA1UEAwwJVG9ycXVlIENBMB4XDTE4MDgxMzEzMjMwMloXDTI4MDgxMDEz
MjMwMlowUDELMAkGA1UEBhMCRlIxDzANBgNVBAgMBkZyYW5jZTEPMA0GA1UECgwG
VG9ycXVlMR8wHQYDVQQDDBZUb3JxdWUgSW50ZXJtZWRpYXRlIENBMIICIjANBgkq
hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwP5ie0MxicK1+HSrwieodyyVzKhVg5pH
vbyOlSKGXzt4L6PQpYRPL/TjBwzSRLayVvVhNn2ExchopunQc4RBb/iqhg0eMfqt
hr2yayCOnXa3ioDZud7sno6Q4pDwKehljucep9k9dbDYrlUr0nO9U6dATqnDl1u3
J7Mz/qOeR92WalweWxmxlcv2JsBI4rfvH43btawECR26d8m6fzBC4gGYYUIm79W2
233NfGVmWXI2kvfmYFZk4QA84wXCtsJ4/9Dnx1VDxM2uoBcTpcanoR1Qb5lcsp/O
8O6tNouh1razRnHrPtp1EyQnuuN1VAN7iAHlYadsawBrnshYvMu+cx7KF68XPFlz
bxCfFcEAdPghuIBhS5Hy5P6og+cBWTvt4du7w/OY759GaE7J5A0UCe6mSiQLLXVo
hCSymBUjotsfDE7158QZdgL+hOr3OppMag5+1ndfcJxw3DoXOFcu66LSjXLVRhH9
+Q1CpuHQTj7cMOPpOu8iS4OvtIq2/KKy2dE1gjTYSHwmxCf3rW+11sSJbsRfY4Hz
TfmfFMYS55Z6XZ5a3H2+ka92Vg2QrArAOerUwQIPMPCyjqRYzGpzAAgRl/CmE2qW
oUYGQJFUWEMZhWNNfGxTqRLd5fB8rlPg5eJqxyzBArrUxbXJbpF/jvqM1I2e7aKO
HHXJwmWfdBMCAwEAAaNmMGQwHQYDVR0OBBYEFP3zst3VSgWirnCoBfdlHBP9pY5r
MB8GA1UdIwQYMBaAFDuNuHRPMlIgyzsY1Kn5SOtg7ImXMBIGA1UdEwEB/wQIMAYB
Af8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDD4gfACvkF
5v9sP0OsIMyUx4fsZmRIuVqJOu4Qul+zB5EDCzl9Hsx16wFCeVWpt+J2Y8j+2w1+
K/u9qZjgCfIFIBPgboH49QUXwyEgQVF2U7ij4Dvzz//Me87qTCJnU83IW6PXz1M0
YHABb70e6cWOheInbNDbYnvvnxCGN/4HfEiYTgvqzibW33hrNEFk1nN48ebxN/a6
e/BHE0lNpzUAwjmY41WX7FQd6ka/eLWAxWzqBoj1IgIvdglML2g0hQzFVcEgiK5N
0JqVLFEHd3B3CBQSCnbNAimCM5t2ZVDAAV/nPKRLto7Fun2gVvJGpsnW6WhwEhg/
/EVsjsnECx2LBS5c0BvbFLWlB7kaKBYYiKd/0J4inw2RtlkP0nNTT/YZKm1s1J+D
TTmOlaZyRSUeU3X0ntRcX2bjdcZqrdfcy4rEp0K3L2tVyW962jmzOMA7vg5Xd1qs
zYYIksFSTog3AN4fLpO8gI1eoiXqnOo+y4WjVY8niaTl93/VWfLFHhvdlDp55kNr
4jBsbcnavER3heB7EaPp7pe45SYoHwHAQIl20Uqpgy85VUuqo7/0ZUFMIe3563VX
RMP6rozoWbFzbjFY/ZY6xJnjr8MpI+MziwVpI+vWur45UVsV2v1ku8T6MRN9VQfo
ziAycIaB8iE8hqg1SX43uuWr8soOT0Kv9A==
-----END CERTIFICATE-----
And this one:
pfsense_ca:
- name: Torque CA
certificate: MIIFhTCCA22gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwUzELMAkGA1UEBhMCRlIx DzANBgNVBAgMBkZyYW5jZTEOMAwGA1UEBwwFUGFyaXMxDzANBgNVBAoMBlRvcnF1 ZTESMBAGA1UEAwwJVG9ycXVlIENBMB4XDTE4MDgxMzEzMjMwMloXDTI4MDgxMDEz MjMwMlowUDELMAkGA1UEBhMCRlIxDzANBgNVBAgMBkZyYW5jZTEPMA0GA1UECgwG VG9ycXVlMR8wHQYDVQQDDBZUb3JxdWUgSW50ZXJtZWRpYXRlIENBMIICIjANBgkq hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwP5ie0MxicK1+HSrwieodyyVzKhVg5pH vbyOlSKGXzt4L6PQpYRPL/TjBwzSRLayVvVhNn2ExchopunQc4RBb/iqhg0eMfqt hr2yayCOnXa3ioDZud7sno6Q4pDwKehljucep9k9dbDYrlUr0nO9U6dATqnDl1u3 J7Mz/qOeR92WalweWxmxlcv2JsBI4rfvH43btawECR26d8m6fzBC4gGYYUIm79W2 233NfGVmWXI2kvfmYFZk4QA84wXCtsJ4/9Dnx1VDxM2uoBcTpcanoR1Qb5lcsp/O 8O6tNouh1razRnHrPtp1EyQnuuN1VAN7iAHlYadsawBrnshYvMu+cx7KF68XPFlz bxCfFcEAdPghuIBhS5Hy5P6og+cBWTvt4du7w/OY759GaE7J5A0UCe6mSiQLLXVo hCSymBUjotsfDE7158QZdgL+hOr3OppMag5+1ndfcJxw3DoXOFcu66LSjXLVRhH9 +Q1CpuHQTj7cMOPpOu8iS4OvtIq2/KKy2dE1gjTYSHwmxCf3rW+11sSJbsRfY4Hz TfmfFMYS55Z6XZ5a3H2+ka92Vg2QrArAOerUwQIPMPCyjqRYzGpzAAgRl/CmE2qW oUYGQJFUWEMZhWNNfGxTqRLd5fB8rlPg5eJqxyzBArrUxbXJbpF/jvqM1I2e7aKO HHXJwmWfdBMCAwEAAaNmMGQwHQYDVR0OBBYEFP3zst3VSgWirnCoBfdlHBP9pY5r MB8GA1UdIwQYMBaAFDuNuHRPMlIgyzsY1Kn5SOtg7ImXMBIGA1UdEwEB/wQIMAYB Af8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDD4gfACvkF 5v9sP0OsIMyUx4fsZmRIuVqJOu4Qul+zB5EDCzl9Hsx16wFCeVWpt+J2Y8j+2w1+ K/u9qZjgCfIFIBPgboH49QUXwyEgQVF2U7ij4Dvzz//Me87qTCJnU83IW6PXz1M0 YHABb70e6cWOheInbNDbYnvvnxCGN/4HfEiYTgvqzibW33hrNEFk1nN48ebxN/a6 e/BHE0lNpzUAwjmY41WX7FQd6ka/eLWAxWzqBoj1IgIvdglML2g0hQzFVcEgiK5N 0JqVLFEHd3B3CBQSCnbNAimCM5t2ZVDAAV/nPKRLto7Fun2gVvJGpsnW6WhwEhg/ /EVsjsnECx2LBS5c0BvbFLWlB7kaKBYYiKd/0J4inw2RtlkP0nNTT/YZKm1s1J+D TTmOlaZyRSUeU3X0ntRcX2bjdcZqrdfcy4rEp0K3L2tVyW962jmzOMA7vg5Xd1qs zYYIksFSTog3AN4fLpO8gI1eoiXqnOo+y4WjVY8niaTl93/VWfLFHhvdlDp55kNr 4jBsbcnavER3heB7EaPp7pe45SYoHwHAQIl20Uqpgy85VUuqo7/0ZUFMIe3563VX RMP6rozoWbFzbjFY/ZY6xJnjr8MpI+MziwVpI+vWur45UVsV2v1ku8T6MRN9VQfo ziAycIaB8iE8hqg1SX43uuWr8soOT0Kv9A==
But when I open pfSense, while the certificate entry exists, it is empty. Am I doing something wrong ? What should be the cert format here ?
Hello everyone,
Issue detected today:
When using a simple WAN CARP VIP, it's not possible to select this VIP as IPSEC interface.
Working in the Pfsense GUI, but not in pfsense_ipsec.
VIP interface are defined like: _vip5f0eebd19b2ea
failed: [****] {"msg": "_vip5f0eebd19b2ea is not a valid interface"}
- name: Create IPSEC tunnels (phase 1)
pfsense_ipsec:
state: "{{ item.state }}"
descr: "{{ item.descr }}"
interface: "_vip5f0eebd19b2ea"
protocol: inet
remote_gateway: "{{ item.gateway }}"
iketype: "{{ item.ike }}"
mode: main
authentication_method: pre_shared_key
preshared_key: "{{ item.key }}"
myid_type: myaddress
peerid_type: peeraddress
I will investigate this later, but probably a simple "interface name checking" issue?
Thanks
Hello,
Without any CA set, we can't add an ldap server to pfsense without triggering an error.
With the following role:
- name: Setup LDAP
pfsense_authserver_ldap:
name: "{{ item.name }}"
host: "{{ item.host }}"
port: "{{ item.port }}"
transport: "{{ item.transport }}"
scope: subtree
basedn: "{{ item.basedn }}"
binddn: "{{ item.binddn }}"
bindpw: "{{ item.bindpw }}"
authcn: "{{ item.authcn }}"
attr_user: samAccountName
attr_member: memberOf
attr_groupobj: group
state: present
with_items:
- "{{ pfsense_ad }}"
I get the following error:
failed: [gw-dmz] (item={u'binddn': u'browse', u'name': u'AD', u'basedn': u'<redacted>', u'host': u'my_ad_server.domain.com', u'bindpw': u'<redacted>', u'scope': u'subtree', u'port': 389, u'transport': u'tcp', u'authcn': u'<redacted>'}) => {"changed": false, "item": {"authcn": "<redacted>", "basedn": "<redacted>", "binddn": "browse", "bindpw": "<redacted>", "host": "my_ad_server.domain.com", "name": "AD", "port": 389, "scope": "subtree", "transport": "tcp"}, "msg": "could not find CA 'None'"}
As you can see, CA field was never set (and it should not be required since it's a TCP connection on 389 without encryption).
This function was added in 2.4.4 by pfsense/pfsense@65b5efa
Maybe you could simply redefine it for older versions?
Hi, I'm a little unsure how to being using this module. It is the first custom one I've tried, and googling what to do is escaping me.
Where do you actually place all the files that are downloaded?
Thanks for your time.
Regards
I have forked this project and attempted to refactor it to work with ansible galaxy collections. This will allow users to install this module like they would a role. This requires Ansible 2.9+ in order to install.
I am working out of the galaxy
branch of my fork https://github.com/tvories/ansible-pfsense/tree/galaxy
I have compiled a local version of the refactored code using ansible-galaxy build
(specifically using ansible 2.10-dev). That gives me a tar.gz of the plugin that I can install in my ansible project using ansible-galaxy collection install opoplawski-pfsense-1.0.0.tar.gz
.
# pfsense.yml
---
- name: Pfsense Rules
hosts: pfsense
become: true
roles:
- pfsense
# roles/pfsense/tasks/vlans.yml
---
# VLAN Configuration
- name: 192.168.1.0/24 - Legacy
opoplawski.pfsense.pfsense_vlan:
interface: "{{ pfsense_lan_nic }}"
vlan_id: 1
descr: 192.168.1.0/24 - Legacy
state: present
- name: 192.168.20.0/24 - Primary
opoplawski.pfsense.pfsense_vlan:
interface: "{{ pfsense_lan_nic }}"
vlan_id: 20
descr: 192.168.20.0/24 - Primary
state: present
- name: 192.168.40.0/24 - Guest WiFi
opoplawski.pfsense.pfsense_vlan:
interface: "{{ pfsense_lan_nic }}"
vlan_id: 40
descr: 192.168.40.0/24 - Guest WiFi
state: present
- name: 192.168.50.0/24 - IoT
opoplawski.pfsense.pfsense_vlan:
interface: "{{ pfsense_lan_nic }}"
vlan_id: 50
descr: 192.168.50.0/24 - IoT
state: present
- name: 192.168.60.0/24 - DMZ
opoplawski.pfsense.pfsense_vlan:
interface: "{{ pfsense_lan_nic }}"
vlan_id: 60
descr: 192.168.60.0/24 - DMZ
state: present
- name: 192.168.70.0/24 - Joey Backup
opoplawski.pfsense.pfsense_vlan:
interface: "{{ pfsense_lan_nic }}"
vlan_id: 70
descr: 192.168.70.0/24 - Joey Backup
state: present
The module appears to import properly after the refactoring. When I run ansible-playbook pfsense.yml
I get the following error:
ansible_collections.opoplawski.pfsense.plugins.module_utils.network.pfsense.pfsense_vlan.__spec__ is None
I am not familiar with developing ansible modules, so I'm hoping this is just a mistake on the refactoring on my part.
The full ansible output:
PLAY [Pfsense Rules] ***********************************************************
TASK [Gathering Facts] *********************************************************
ok: [pfsense.mcbadass.local]
TASK [pfsense : include_tasks] *************************************************
included: /ansible/playbooks/roles/pfsense/tasks/vlans.yml for pfsense.mcbadass.local
TASK [pfsense : 192.168.1.0/24 - Legacy] ***************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ValueError: ansible_collections.opoplawski.pfsense.plugins.module_utils.network.pfsense.pfsense_vlan.__spec__ is None
fatal: [pfsense.mcbadass.local]: FAILED! => {"msg": "Unexpected failure during module execution.", "stdout": ""}
PLAY RECAP *********************************************************************
pfsense.mcbadass.local : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
It would be great if it would be possible to add User.
So VPN access can be Created Automatically (When no LDAP is aviable)
I would find really useful to be able to edit pfsense haproxy entries using this module.
I know that haproxy is an optional module but I observed that this is the one that I need to touch most often for adding SSL offloading for backend services running on VMs and containers.
HAproxy happens to run on pfsense and does all the SSL offloading for these, avoiding the need to manage certificates for each of these services.
Hi, looks like a great project but I'm getting an error when I run against pfsense 2.4.5-RELEASE
I can ssh:
ssh '[email protected]'
pfSense - Netgate Device ID: f7ab17f2494785a37c73
*** Welcome to pfSense 2.4.5-RELEASE (amd64) on isolated-pfsense1 ***
WAN (wan) -> vtnet0 -> v4: 138.80.128.139/23
LAN (lan) -> vtnet1 -> v4: 192.168.0.1/24
0) Logout (SSH only) 9) pfTop
1) Assign Interfaces 10) Filter Logs
2) Set interface(s) IP address 11) Restart webConfigurator
3) Reset webConfigurator password 12) PHP shell + pfSense tools
4) Reset to factory defaults 13) Update from console
5) Reboot system 14) Disable Secure Shell (sshd)
6) Halt system 15) Restore recent configuration
7) Ping host 16) Restart PHP-FPM
8) Shell
Enter an option:
My playbook looks like this:
(isolatednet) ~/g/isolatednet> cat provision_pfsense_users.yml
---
# Playbook to create users
- hosts: all
connection: paramiko
gather_facts: false
tasks:
- name: Add test user
pfsensible.core.user:
name: s123456
password: "{{ 'test' | password_hash('blowfish','1234567890123456789012') }}"
Inventory:
(isolatednet) ~/g/isolatednet> cat inventory.ini
[vpn]
pf1 ansible_ssh_host=138.80.128.139 ansible_ssh_user=admin ansible_password=pass
However, if I run the playbook it doesn't work:
(isolatednet) ~/g/isolatednet[99]> ansible-playbook -i inventory.ini provision_pfsense_users.yml -vvv
ansible-playbook 2.9.9
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/jtuckey/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/jtuckey/g/isolatednet/isolatednet/lib/python3.8/site-packages/ansible
executable location = /home/jtuckey/g/isolatednet/isolatednet/bin/ansible-playbook
python version = 3.8.2 (default, Apr 27 2020, 15:53:34) [GCC 9.3.0]
Using /etc/ansible/ansible.cfg as config file
host_list declined parsing /home/jtuckey/g/isolatednet/inventory.ini as it did not pass its verify_file() method
script declined parsing /home/jtuckey/g/isolatednet/inventory.ini as it did not pass its verify_file() method
auto declined parsing /home/jtuckey/g/isolatednet/inventory.ini as it did not pass its verify_file() method
yaml declined parsing /home/jtuckey/g/isolatednet/inventory.ini as it did not pass its verify_file() method
Parsed /home/jtuckey/g/isolatednet/inventory.ini inventory source with ini plugin
PLAYBOOK: provision_pfsense_users.yml ************************************************************************************************
1 plays in provision_pfsense_users.yml
PLAY [all] ***************************************************************************************************************************
META: ran handlers
TASK [Add test user] *****************************************************************************************************************
task path: /home/jtuckey/g/isolatednet/provision_pfsense_users.yml:7
<138.80.128.139> ESTABLISH PARAMIKO SSH CONNECTION FOR USER: admin on PORT 22 TO 138.80.128.139
<138.80.128.139> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /tmp/ans `"&& mkdir /tmp/ans/ansible-tmp-1590136787.2811134-52550-142443789600286 && echo ansible-tmp-1590136787.2811134-52550-142443789600286="` echo /tmp/ans/ansible-tmp-1590136787.2811134-52550-142443789600286 `" ) && sleep 0'
fatal: [pf1]: UNREACHABLE! => {
"changed": false,
"msg": "Failed to create temporary directory.In some cases, you may have been able to authenticate and did not have permissions on the target directory. Consider changing the remote tmp path in ansible.cfg to a path rooted in \"/tmp\", for more error information use -vvv. Failed command was: ( umask 77 && mkdir -p \"` echo /tmp/ans `\"&& mkdir /tmp/ans/ansible-tmp-1590136787.2811134-52550-142443789600286 && echo ansible-tmp-1590136787.2811134-52550-142443789600286=\"` echo /tmp/ans/ansible-tmp-1590136787.2811134-52550-142443789600286 `\" ), exited with result 2",
"unreachable": true
}
PLAY RECAP ***************************************************************************************************************************
pf1 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
I tried running the command directly but I'm not sure what the problem is:
(isolatednet) ~/g/isolatednet[4]> ssh [email protected] /bin/sh -c '( umask 77 && mkdir -p "` echo /tmp/ans `"&& mkdir /tmp/ans/ansible-tmp-1590136787.2811134-52550-142443789600286 && echo ansible-tmp-1590136787.2811134-52550-142443789600286="` echo /tmp/ans/ansible-tmp-1590136787.2811134-52550-142443789600286 `" ) && sleep 0'
Bad -c option
(isolatednet) ~/g/isolatednet[2]>
Is there anything obvious I'm doing wrong? I'm a bit of a noob with Ansible but really like the idea of using it. Any help is much appreciated. My host is Ubuntu 20.04, and I tried using ansible from apt and also from a pip install:
(isolatednet) ~/g/isolatednet[2]> lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04 LTS
Release: 20.04
Codename: focal
(isolatednet) ~/g/isolatednet> ansible --version
ansible 2.9.9
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/jtuckey/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/jtuckey/g/isolatednet/isolatednet/lib/python3.8/site-packages/ansible
executable location = /home/jtuckey/g/isolatednet/isolatednet/bin/ansible
python version = 3.8.2 (default, Apr 27 2020, 15:53:34) [GCC 9.3.0]
I have the following playbook (I'm new to Ansible Playbooks, so I may have mistyped something):
---
- name: Add RFC1918 Alias
hosts: all
collections:
- pfsensible.core
tasks:
- name: Add Alias
pfsense_alias:
name: RFC1918
type: network
address: "10.0.0.0/8 172.16.0.0/12 192.168.0.0/16"
state: present
I keep getting the following error:
ERROR! couldn't resolve module/action 'pfsense_alias'. This often indicates a misspelling, missing collection, or incorrect module path.
I have tried creating the following file in both the root of my SCM and inside the directory with my playbook as roles/requirements.yaml
---
- src: pfsensible.core
Nothing seems to help. Since I'm new, I'm not sure how to get AWX to download the module.
Hello,
I've been trying the module with a empty pfsense installation:
And when I run the playbook, I get the following error:
---
- hosts: pfsense
tasks:
- name: Add adservers alias
pfsense_alias:
name: adservers
address: 10.0.0.1 10.0.0.2
state: present
type: host
The full traceback is:
Traceback (most recent call last):
File "<stdin>", line 113, in <module>
File "<stdin>", line 105, in _ansiballz_main
File "<stdin>", line 48, in invoke_module
File "/tmp/ansible_pfsense_alias_payload_A_n1LQ/__main__.py", line 93, in <module>
File "/tmp/ansible_pfsense_alias_payload_A_n1LQ/__main__.py", line 88, in main
File "/tmp/ansible_pfsense_alias_payload_A_n1LQ/ansible_pfsense_alias_payload.zip/ansible/module_utils/networking/pfsense/pfsense_alias.py", line 188, in run
File "/tmp/ansible_pfsense_alias_payload_A_n1LQ/ansible_pfsense_alias_payload.zip/ansible/module_utils/networking/pfsense/pfsense_alias.py", line 161, in _params_to_alias
File "/tmp/ansible_pfsense_alias_payload_A_n1LQ/ansible_pfsense_alias_payload.zip/ansible/module_utils/networking/pfsense/pfsense_alias.py", line 134, in _validate_params
File "/tmp/ansible_pfsense_alias_payload_A_n1LQ/ansible_pfsense_alias_payload.zip/ansible/module_utils/networking/pfsense/pfsense.py", line 67, in get_interface_pfsense_by_name
AttributeError: 'NoneType' object has no attribute 'text'
If you navigate to /interfaces.php?if=wan, you save without changes and you apply, the error disappear.
Interfaces that have been setup for DHCP and/or do not have an address yet fail _check_overlaps
when trying to setup an interface because it expects to have a valid IP address but the "address" it receives is u'dhcp/None'
My temporary fix was to comment out the overlap check.
Traceback (most recent call last):
File \"/root/.ansible/tmp/ansible-tmp-1578515006.8685193-152090955772829/AnsiballZ_pfsense_interface.py\", line 102, in <module>
_ansiballz_main()
File \"/root/.ansible/tmp/ansible-tmp-1578515006.8685193-152090955772829/AnsiballZ_pfsense_interface.py\", line 94, in _ansiballz_main invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
File \"/root/.ansible/tmp/ansible-tmp-1578515006.8685193-152090955772829/AnsiballZ_pfsense_interface.py\", line 40, in invoke_module
runpy.run_module(mod_name='ansible.modules.pfsense_interface', init_globals=None, run_name='__main__', alter_sys=True)
File \"/usr/local/lib/python2.7/runpy.py\", line 188, in run_module
fname, loader, pkg_name)
File \"/usr/local/lib/python2.7/runpy.py\", line 82, in _run_module_code
mod_name, mod_fname, mod_loader, pkg_name)
File \"/usr/local/lib/python2.7/runpy.py\", line 72, in _run_code
exec code in run_globals
File \"/tmp/ansible_pfsense_interface_payload_AadC14/ansible_pfsense_interface_payload.zip/ansible/modules/pfsense_interface.py\", line 137, in <module>
File \"/tmp/ansible_pfsense_interface_payload_AadC14/ansible_pfsense_interface_payload.zip/ansible/modules/pfsense_interface.py\", line 132, in main
File \"/tmp/ansible_pfsense_interface_payload_AadC14/ansible_pfsense_interface_payload.zip/ansible/module_utils/network/pfsense/pfsense_module_base.py\", line 182, in run
File \"/tmp/ansible_pfsense_interface_payload_AadC14/ansible_pfsense_interface_payload.zip/ansible/module_utils/network/pfsense/pfsense_interface.py\", line 114, in _params_to_obj
File \"/tmp/ansible_pfsense_interface_payload_AadC14/ansible_pfsense_interface_payload.zip/ansible/module_utils/network/pfsense/pfsense_interface.py\", line 73, in _check_overlaps
File \"/tmp/ansible_pfsense_interface_payload_AadC14/ansible_pfsense_interface_payload.zip/ansible/module_utils/compat/ipaddress.py\", line 261, in ip_network
ValueError: u'dhcp/None' does not appear to be an IPv4 or IPv6 network
I hope you plan to merge it to ansible from day one. I am sure it may take some time to make it ready but it would be really nice to see it as part of it, when I install ansible 2.x :)
Not much of a python guys so not sure if I'm just not using it correctly, but it appears that the pfsense.core.interface only allows creating and removing an interface. Update attempts fail on a "KeyError: 'descr'" message.
For "Destination" (and source I guess) in pfsense_rule, the format seems to be WAN(network):Port or WAN(IP) (without a port). I want to add a rule which has a destination of "WAN Address" and port 443. I tried destination=WANIP:443 but it returns error:
"Cannot parse address WANIP, not IP or alias"
'wanip' is one of the dropdown (select) options on the Pfsense GUI so should work, right?
It would be grand if dhcp could be managed for example for setting fixed dhcp addresses with hostnames.
Unbound would be cool too, if I deploy guest vm's with fixed ip's (on guest OS level) it would be grand if I can push a hostname to unbound to have it resolved.
Are there any plans to make this work too?
Thanks!
Hi,
I'm trying to use your module to manage aliases, but unfortunately, it seems to corrupt configuration. Here's a sample from my role:
pfsense_alias:
name: admdmz
type: host
address: 10.2.1.5
(It's pretty much the only task, for testing purposes).
After applying it, it seems successful:
TASK [pfsense : Create aliases] **********************************************************************
changed: [gw.dmz]
But when I try to reload web ui (or reapply task), I get the following error:
Fatal error: Uncaught Error: Cannot create references to/from string offsets in /etc/inc/xmlparse.inc:71 Stack trace: #0 [internal function]: startElement(Resource id #6, 'UPDATEFIB', Array) #1 /etc/inc/xmlparse.inc(186): xml_parse(Resource id #6, 'rface>\n\t\t\t\t\n\t\t\t\t`
Could you please check ? Thanks
Hello,
Thanks for this awesome plugins.
I have a small probleme or i may be a bit silly :
i can create rules with no problemes. but for deleting it, it seems that it can't found it and dont make the changes.
Here is my task :
vars :
ansible_python_interpreter: /usr/local/bin/python2.7
tasks:
- name: Del Client SSO
pfsensible.core.rule:
name : "SSO-{{ sso_ip_disallow }}"
action: pass
interface: wan
ipprotocol: inet
protocol: tcp
source: "{{ sso_ip_disallow }}"
destination: 192.168.11.112
destination_port: WEBPort
disabled: true
state: absent
and here is the -vvv
# ansible-playbook -i inventory/inventory.yml playbooks/metier/del-user-sso.yml -e sso_ip_disallow="77.153.149.224" -vvv [17:29:14]
ansible-playbook 2.9.6
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible-playbook
python version = 2.7.13 (default, Sep 26 2018, 18:42:22) [GCC 6.3.0 20170516]
Using /etc/ansible/ansible.cfg as config file
host_list declined parsing /root/inventory/inventory.yml as it did not pass its verify_file() method
script declined parsing /root/inventory/inventory.yml as it did not pass its verify_file() method
Parsed /root/inventory/inventory.yml inventory source with yaml plugin
PLAYBOOK: del-user-sso.yml ******************************************************************************************************************************************************************************************
1 plays in playbooks/metier/del-user-sso.yml
PLAY [ASA config] ***************************************************************************************************************************************************************************************************
META: ran handlers
TASK [Del Client SSO] ***********************************************************************************************************************************************************************************************
task path: /root/playbooks/metier/del-user-sso.yml:13
<89.30.116.123> ESTABLISH SSH CONNECTION FOR USER: None
<89.30.116.123> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/a055941476 89.30.116.123 '/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
<89.30.116.123> (0, '/root\n', '')
<89.30.116.123> ESTABLISH SSH CONNECTION FOR USER: None
<89.30.116.123> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/a055941476 89.30.116.123 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1584376158.6-53007017427214 `" && echo ansible-tmp-1584376158.6-53007017427214="` echo /root/.ansible/tmp/ansible-tmp-1584376158.6-53007017427214 `" ) && sleep 0'"'"''
<89.30.116.123> (0, 'ansible-tmp-1584376158.6-53007017427214=/root/.ansible/tmp/ansible-tmp-1584376158.6-53007017427214\n', '')
Using module file /root/playbooks/metier/collections/ansible_collections/pfsensible/core/plugins/modules/rule.py
<89.30.116.123> PUT /root/.ansible/tmp/ansible-local-292230pjPCH/tmpVT4Y0t TO /root/.ansible/tmp/ansible-tmp-1584376158.6-53007017427214/AnsiballZ_rule.py
<89.30.116.123> SSH: EXEC sftp -b - -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/a055941476 '[89.30.116.123]'
<89.30.116.123> (0, 'sftp> put /root/.ansible/tmp/ansible-local-292230pjPCH/tmpVT4Y0t /root/.ansible/tmp/ansible-tmp-1584376158.6-53007017427214/AnsiballZ_rule.py\n', '')
<89.30.116.123> ESTABLISH SSH CONNECTION FOR USER: None
<89.30.116.123> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/a055941476 89.30.116.123 '/bin/sh -c '"'"'chmod u+x /root/.ansible/tmp/ansible-tmp-1584376158.6-53007017427214/ /root/.ansible/tmp/ansible-tmp-1584376158.6-53007017427214/AnsiballZ_rule.py && sleep 0'"'"''
<89.30.116.123> (0, '', '')
<89.30.116.123> ESTABLISH SSH CONNECTION FOR USER: None
<89.30.116.123> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/a055941476 -tt 89.30.116.123 '/bin/sh -c '"'"'sudo -H -S -n -u root /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-pzmrixegthyixupzavptfgdkaxtgqjdj ; /usr/local/bin/python2.7 /root/.ansible/tmp/ansible-tmp-1584376158.6-53007017427214/AnsiballZ_rule.py'"'"'"'"'"'"'"'"' && sleep 0'"'"''
Escalation succeeded
<89.30.116.123> (0, '\r\n{"commands": [], "added": [], "stdout": "", "deleted": [], "changed": false, "modified": [], "stderr": "", "invocation": {"module_args": {"protocol": "tcp", "disabled": true, "floating": null, "in_queue": null, "before": null, "log": null, "statetype": "keep state", "destination": "192.168.11.112", "ackqueue": null, "gateway": "default", "source": "77.153.149.224", "state": "absent", "tracker": null, "ipprotocol": "inet", "direction": null, "after": null, "out_queue": null, "icmptype": "any", "action": "pass", "interface": "wan", "destination_port": "WEBPort", "name": "SSO 77.153.149.224", "queue": null, "source_port": null}}, "diff": {"after": {}, "before": {}}}\r\n', 'Shared connection to 89.30.116.123 closed.\r\n')
<89.30.116.123> ESTABLISH SSH CONNECTION FOR USER: None
<89.30.116.123> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/a055941476 89.30.116.123 '/bin/sh -c '"'"'rm -f -r /root/.ansible/tmp/ansible-tmp-1584376158.6-53007017427214/ > /dev/null 2>&1 && sleep 0'"'"''
<89.30.116.123> (0, '', '')
ok: [pf01] => {
"added": [],
"changed": false,
"commands": [],
"deleted": [],
"diff": {
"after": {},
"before": {}
},
"invocation": {
"module_args": {
"ackqueue": null,
"action": "pass",
"after": null,
"before": null,
"destination": "192.168.11.112",
"destination_port": "WEBPort",
"direction": null,
"disabled": true,
"floating": null,
"gateway": "default",
"icmptype": "any",
"in_queue": null,
"interface": "wan",
"ipprotocol": "inet",
"log": null,
"name": "SSO 77.153.149.224",
"out_queue": null,
"protocol": "tcp",
"queue": null,
"source": "77.153.149.224",
"source_port": null,
"state": "absent",
"statetype": "keep state",
"tracker": null
}
},
"modified": [],
"stderr": "",
"stderr_lines": [],
"stdout": "",
"stdout_lines": []
}
META: ran handlers
META: ran handlers
PLAY RECAP **********************************************************************************************************************************************************************************************************
pf01 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Thanks for the help.
Sabri
Hi,
We use some of these modules to deploy firewalls with a default rulebase and use the 'pfsense_rule_separator' to add some separators. This works perfectly fine on the WAN interface, but once we try to add the separators on the LAN interface, they don't show up. Diving into the config.xml, it seems they are added, but the 'row' is incorrect.
<sep0>
<color>bg-info</color>
<text><![CDATA[Management and Monitoring]]></text>
<row>fr6</row>
<if>lan</if>
</sep0>
It adds it on fr6, but if I add the same separator correctly, it should be fr0.
<separator>
<lan>
<sep0>
<row>fr0</row>
<text><![CDATA[Management and Monitoring]]></text>
<color>bg-info</color>
<if>lan</if>
</sep0>
</lan>
</separator>
I can reproduce this if you need more output. I ran it with -vv but it doesn't give much output apart from telling me it added the separators.
currently installing the scripts in following GCP instance : Linux , 4.19.0-9-cloud-amd64 #1 SMP Debian 4.19.118-2 (2020-04-29) x86_64 GNU/Linux . when i run the command there is error as follows :
ansible-galaxy collection install pfsensible.core
- downloading role 'collection', owned by
[WARNING]: - collection was NOT installed successfully: Content has no field named 'owner'
I was able to get everything connected and configured but when I try to set an alias or any other setting I get Permision denied.
I made sure the user I created has full admin access to my pfSense router.
Here is the exact output of the playbook:
PLAY [pfSense Testing] *************************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************************************************************************************************************************************ok: [192.168.1.1]
TASK [Test Group] ******************************************************************************************************************************************************************************************************************************************************************************fatal: [192.168.1.1]: FAILED! => {"changed": false, "module_stderr": "Shared connection to 192.168.1.1 closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File \"/home/ansible/.ansible/tmp/ansible-tmp-1557281188.07-38654084696534/AnsiballZ_pfsense_alias.py\", line 113, in <module>\r\n _ansiballz_main()\r\n File \"/home/ansible/.ansible/tmp/ansible-tmp-1557281188.07-38654084696534/AnsiballZ_pfsense_alias.py\", line 105, in _ansiballz_main\r\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n File \"/home/ansible/.ansible/tmp/ansible-tmp-1557281188.07-38654084696534/AnsiballZ_pfsense_alias.py\", line 48, in invoke_module\r\n imp.load_module('__main__', mod, module, MOD_DESC)\r\n File \"/tmp/ansible_pfsense_alias_payload_WcBCE0/__main__.py\", line 93, in <module>\r\n File \"/tmp/ansible_pfsense_alias_payload_WcBCE0/__main__.py\", line 89, in main\r\n File \"/tmp/ansible_pfsense_alias_payload_WcBCE0/ansible_pfsense_alias_payload.zip/ansible/module_utils/networking/pfsense/pfsense_alias.py\", line 181, in commit_changes\r\n File \"/tmp/ansible_pfsense_alias_payload_WcBCE0/ansible_pfsense_alias_payload.zip/ansible/module_utils/networking/pfsense/pfsense.py\", line 435, in write_config\r\n File \"/usr/local/lib/python2.7/shutil.py\", line 316, in move\r\n copy2(src, real_dst)\r\n File \"/usr/local/lib/python2.7/shutil.py\", line 144, in copy2\r\n copyfile(src, dst)\r\n File \"/usr/local/lib/python2.7/shutil.py\", line 97, in copyfile\r\n with open(dst, 'wb') as fdst:\r\nIOError: [Errno 13] Permission denied: '/cf/conf/config.xml'\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
to retry, use: --limit @/home/tadmin/ansibletesting/ansible-pfsense/test.retry
PLAY RECAP *************************************************************************************************************************************************************************************************************************************************************************************192.168.1.1 : ok=1 changed=0 unreachable=0 failed=1
And here is my playbook:
---
- name: pfSense Testing
hosts: pfsense
tasks:
- name: Test Group
pfsense_alias:
name: "Test1"
address: 10.9.92.1
type: host
state: present
Hi,
At the moment, the config XML cannot be written / read as-is because some fields are HTML-escaped before being written into a CDATA tag.
The most noticeable result is that calling this plugin breaks my LDAP config.
I have already opened an issue upstream but I doubt they are going to work on it since it's an edge case.
I also made a PR which was rejected because it breaks existing configs: pfsense/pfsense#4432.
I don't really know how we could work around this issue. I have looked at pfSense's code, specifically xml_set_character_data_handler
which calls this cData
function and it isn't able to parse double-escaped attributes such as
<ldap_extended_query>memberOf=CN=Some Group,OU=One &amp; Two,DC=blah,DC=local</ldap_extended_query>
which is what this module produces.
The problem is that, to pfSense, parsing both of these returns &
:
<ldap_extended_query>&</ldap_extended_query>
<ldap_extended_query><![CDATA[&]]></ldap_extended_query>
Maybe we could process all special fields and enclose them in CDATA
. However, we must also call html.escape
when reading them. There are many corner cases to be aware of. I think a good test value is &ΓΌ
because the former will be escaped by Python while the latter will only be escaped by PHP's htmlentities
.
Hi All
I am new to Ansible, I'm trying to copy a repo file from control node to manage node and got the below error when executing my playbook using privilege escalation
Error:
[usser1@server1ansible]$ ansible new -m ping -b
SSH password:
BECOME password[defaults to SSH password]:
10.192.128.201 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"module_stderr": "Shared connection to 10.192.128.201 closed.\r\n",
"module_stdout": "\r\n",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
My Ansible configuration file(Ansible.cfg) has the below
[defaults]
inventory = ./inventory
ask_pass = true
host_key_checking = false
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = true
My user has the privilege to execute sudo commands on both the nodes. Please help to fix the error.
Thank you
I have been using this for a while and it works well with pfsense v2.4.5p1. I am planning to upgrade to pfsense 2.5.0 CE. Will it work for pfsense 2.5.0?. Thanks!
Hi,
In addition to setting the user's groupname
, pfsense_user
should add the user's uid
to the related group's member
attribute.
I'm trying to get basic setup functionality working for the following play:
- name: Configure pfSense
hosts: pfsense
remote_user: 'root'
collections:
- pfsensible.core
tasks:
- name: General setup
pfsensible.core.setup:
timezone: America/Chicago
I've installed the collection via ansible-galaxy collection install pfsensible.core -p ./collections
and have set collections_paths = collections
in ansible.cfg
.
The setup module fails with the following error:
$ ansible-playbook --inventory hosts pfsense.yml
PLAY [Configure pfSense] ******************************************************************************************
TASK [Gathering Facts] ********************************************************************************************
fatal: [pfsense]: FAILED! => changed=false
ansible_facts: {}
failed_modules:
setup:
ansible_facts:
discovered_interpreter_python: /usr/local/bin/python2.7
failed: true
invocation:
module_args:
gather_subset:
- all
gather_timeout: 10
msg: 'Unsupported parameters for (setup) module: gather_subset, gather_timeout Supported parameters include: dashboardavailablewidgetspanel, dashboardcolumns, disablealiaspopupdetail, dns_addresses, dns_gateways, dns_hostnames, dnsallowoverride, dnslocalhost, domain, hostname, interfacessort, language, logincss, loginshowhost, requirestatefilter, roworderdragging, statusmonitoringsettingspanel, systemlogsfilterpanel, systemlogsmanagelogpanel, timeservers, timezone, webguicss, webguifixedmenu, webguihostnamemenu, webguileftcolumnhyper'
msg: |-
The following modules failed to execute: setup
PLAY RECAP ********************************************************************************************************
pfsense : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
Version information from the pfSense web UI:
2.4.4-RELEASE-p3 (amd64)
built on Wed May 15 18:53:44 EDT 2019
FreeBSD 11.2-RELEASE-p10
The system is on the latest version.
Version information updated at Mon Mar 23 19:05:18 UTC 2020
Hi,
I tried to use the module to change user attributes and it did not work without a password specified. I think you need this:
diff --git a/library/pfsense_user.py b/library/pfsense_user.py
index 13e4292..b731ed0 100644
--- a/library/pfsense_user.py
+++ b/library/pfsense_user.py
@@ -147,11 +147,12 @@ class pfSenseUser(object):
changed = False
stdout = None
stderr = None
- if re.match(r'\$2b\$', user['password']):
- user['bcrypt-hash'] = user['password']
- else:
- self.module.fail_json(msg='Password (%s) does not appear to be a bcrypt hash' % user['password'])
- del user['password']
+ if 'password' in user:
+ if re.match(r'\$2b\$', user['password']):
+ user['bcrypt-hash'] = user['password']
+ else:
+ self.module.fail_json(msg='Password (%s) does not appear to be a bcrypt hash' % user['password'])
+ del user['password']
# Allow authorizedkeys to be clear or base64 encoded
if 'authorizedkeys' in user and 'ssh-' in user['authorizedkeys']:
user['authorizedkeys'] = base64.b64encode(user['authorizedkeys'])
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.