ibm-security / isam-ansible-collection Goto Github PK
View Code? Open in Web Editor NEWAnsible Collection for providing ISAM Modules, Roles and Playbooks.
License: Apache License 2.0
Ansible Collection for providing ISAM Modules, Roles and Playbooks.
License: Apache License 2.0
Hello,
When I try to execute a playbook with role upload_extension, it throw error messages with HTTP Error code 405 - Not allowed on docker container ISAM or 406-Not acceptable on VMWare VA.
A sample play book like this:
it will be failed at verify task with following error message:
ansible.module_utils.connection.ConnectionError: Error> IBMError, action: ibmsecurity.isam.aac.extensions.verify Exception: ('HTTP Return code: 405', '')
fatal: [lmi.isamva.xxx.com]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n File \"/root/.ansible/tmp/ansible-local-9022960tyaylut/ansible-tmp-1661440645.085202-902491-264274484717115/AnsiballZ_isam.py\", line 100, in <module>\n _ansiballz_main()\n File \"/root/.ansible/tmp/ansible-local-9022960tyaylut/ansible-tmp-1661440645.085202-902491-264274484717115/AnsiballZ_isam.py\", line 92, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File \"/root/.ansible/tmp/ansible-local-9022960tyaylut/ansible-tmp-1661440645.085202-902491-264274484717115/AnsiballZ_isam.py\", line 41, in invoke_module\n run_name='__main__', alter_sys=True)\n File \"/usr/lib64/python3.6/runpy.py\", line 205, in run_module\n return _run_module_code(code, init_globals, run_name, mod_spec)\n File \"/usr/lib64/python3.6/runpy.py\", line 96, in _run_module_code\n mod_name, mod_spec, pkg_name, script_name)\n File \"/usr/lib64/python3.6/runpy.py\", line 85, in _run_code\n exec(code, run_globals)\n File \"/tmp/ansible_ibm.isam.isam_payload_y0yfzcyd/ansible_ibm.isam.isam_payload.zip/ansible_collections/ibm/isam/plugins/modules/isam.py\", line 130, in <module>\n File \"/tmp/ansible_ibm.isam.isam_payload_y0yfzcyd/ansible_ibm.isam.isam_payload.zip/ansible_collections/ibm/isam/plugins/modules/isam.py\", line 110, in main\n File \"/tmp/ansible_ibm.isam.isam_payload_y0yfzcyd/ansible_ibm.isam.isam_payload.zip/ansible/module_utils/connection.py\", line 200, in __rpc__\nansible.module_utils.connection.ConnectionError: Error> IBMError, action: ibmsecurity.isam.aac.extensions.verify Exception: ('HTTP Return code: 405', '')\n",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
Could you please help me figure out the actual cause? what I can do is just pass the file name with absolute path.
As of Ansible 2.4 (or earlier?), it is stated that usage of "- include:" such as in the role first_steps is deprecated and should be replaced with "-include_tasks:" (which was made available starting in in 2.4).
Since the collection framework requires at least version Ansible 2.9 to work, I am assuming it is safe to update code to use include_tasks in the collection framework implementation of the first_steps role.
Will see to push a patch soon.
There's a missing line to start the second task in roles/add_cluster_node/tasks/main.yml file. The first task "stat" is then in conflict with "ibm.isam.isam" because of this.
The playbook crashes with a ERROR! conflicting action statements: stat, ibm.isam.isam
Missing the first "- name: " line in ibm/isam/roles/set_ldap_root_pw/tasks/main.yml:
ibm.isam.isam: log: "{{ log_level | default('INFO') }}" force: "{{ force | default(False) }}" action: ibmsecurity.isam.web.embedded_ldap.admin.set_pw isamapi: notify: Commit Changes
ERROR! The tasks/main.yml file for role 'set_ldap_root_pw' must contain a list of tasks
Also missing the "password" parameter for the isamapi call.
Hello,
Is there any role available to configure reverse proxy instance to configure the Authentication and Context Based Access service ? Upon observation, behind the hood it looks like this is the api call being leveraged
https://appliancehost/wga/reverseproxy/rp-instance/authsvc_config
If there is no such role available, which particular python code has function to get this done via custom role?
The first_steps role only uses "inventory_hostname", while it should honor ansible_host as well.
As documented here: ibm/isam/plugins/connection/isam.py
In recent versions of Ansible (problem started for me on ansible core 2.13.4, but may exist in earlier versions), the ibm.isam.isam connection no longer works.
TASK [ibm.isam.configure_reverseproxy_instances : Configure reverse proxy instances] *********************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'Connection' object has no attribute 'nonetype'
fatal: [isam]: FAILED! => {"msg": "Unexpected failure during module execution.", "stdout": ""}
Hello,
When I use the STS chain ansible role to create the STS chain (not template) I see below error: "msg": "Error> action does not have the right set of arguments or there is a code bug!
Here is the YAML playbook.
I am pretty sure, the parameters are correct as the similar payload works for RESTAPI via postman. Just thinking if the ansible role for STS chain is tested for this usecase, if so, can someone share me a working YAML?.. Please suggest.
Thanks,
Chandra.
Please see this issue, it's repeated here.
IBM-Security/isam-ansible-roles#172
Please change the order of handlers, so "Commit and restart" is first. This avoids problems where commiting changes without restarting causes the appliance to become unresponsive.
https://github.com/IBM-Security/isam-ansible-roles/pull/187/files
Ran into an error in:
roles/aac/configure_runtime_template_root/tasks/include_sync_runtime_template_root.yml
Where in the last task the following fact is generated:
- name: "[sync_up] Define dynamic runtime template containing directories and files to be created/uploaded"
set_fact:
runtime_template_root: "{{ hostvars[inventory_hostname].runtime_template_root }} + {{ directory_updates }} + {{ file_updates }}"
On my Ansible host with Ansible Core 2.13.3 the output was a string instead of list. In order to maintain a list I had to change it to the following:
- name: "[sync_up] Define dynamic runtime template containing directories and files to be created/uploaded"
set_fact:
runtime_template_root: "{{ hostvars[inventory_hostname].runtime_template_root + directory_updates + file_updates }}"
The output is not usable in string format and will cause errors later in the playbooks.
I looked through the Ansible changelog but couldn't find a breaking change. Did IBM test this on newer Ansible versions?
Include is going to be deprecated with a next version of Ansible.
It should be replaced with include_tasks.
Attempted to udpate the server certificate using update_management_ssl_cert role, but failed due to the following error.
Error> action does not have the right set of arguments or there is a code bug! Options: isamAppliance=self.isam_server, force=False, certificate="/work/server-cert2.p12"
So updated as follows and tried to run again.
- name: Update management ssl certificate Mod
ibm.isam.isam:
log: "{{ log_level | default('INFO') }}"
force: "{{ force | default(False) }}"
action: ibmsecurity.isam.base.management_ssl_certificate.set
isamapi:
certificate: "{{ update_management_ssl_cert_cert }}"
password: "{{ update_management_ssl_cert_pwd }}" <-- here
when: update_management_ssl_cert_cert is defined and update_management_ssl_cert_pwd is defined
notify: Commit Changes
But it failed with "TypeError: warn requires a string not a <class 'NoneType'>" error.
This role was successful when I ran it a few years ago, has anything changed?
Since personal certificate is PKCS 12 file with extension name .p12 which is password protected personal certificate.
the role execution need pass the password, but the role task main.yml did not pass this parameter.
When I create a new API protection client in ISAM, I am able to set the value for requirePkce to either true or false and I have no problem with this. However, when I try to update an existing definition, the following occurs:
If the value of requirePkce (labelled as "Require PKCE(RFC 7636):" in the ISAM console) is set to false, I can set it to true successfully using the ISAM Ansible roles.
However, if the value of requirePkce in set to true, I can not set it to false using the ISAM Ansible roles. I get no error, and no change is attempted.
It appears that the compare step is not detecting a change in the value of requirePkce, but this is only happening when I try to set the value of requirePkce for an existing API protection client from true to false.
Hello,
I've been reviewing lately what ansible offers as plug-in extensions and while I'm comparing that towards what this collection is using, I thought we could make this collection much friendly to ansible usage and way of working.
So far, I've in mind to:
Advantages of this approach:
Some features I'd like to see:
More ideas are welcome,
Cédric S.
Fails with error 502, on isam 10.0.1
Be aware, there is an APAR for ISVA v10.0.5. The REST API uses “case_sensitive” while the junction output uses “case insensitive”. The resulting junction is created successfully but the pdadmin server task show output shows the opposite behavior.
The APAR fix will change the REST API command to create a junction. The APAR fix changes the parameter "case_sensitive_url" to become "case_insensitive_url". The APAR fix matches the text in the LMI. The APAR fix will be included in v10.0.6.
"case_sensitive_url":"no" <-- old method
"case_insensitive_url":"yes" <-- v10.0.6 method
APAR Error description:
In the following text, pay careful attention to the use of sensitive and insensitive.
When you create a junction with a REST API command and specify JSON with "case_sensitive_url":"no", the resulting junction show output will show "Case insensitive URLs: no". The no value is consistent, but sensitive/insensitive words have been switched. Unexpectedly, the opposite behavior for the setting is now configured.
In the isam-ansible-collection-master/playbooks/base/extract_certificates.yml file, there is a '/' in the role name causing the ansible-playbook command to fail with "no role found".
should be:
Role and example playbook missing for Redis configuration
I'm having trouble creating an ISAM sysaccount that is assigned to groups. I can see there is a parameter but cannot see an example showing the expected format. Can someone show me an example please?
I cannot figure out how to use this role, the playbook provided in the collection does not work for me. I've seen there may be one or two parameters. My test playbook looks like this. What am I doing wrong? I've tried "file_path" and "filename" instead of path and file, as well as using the playbook in the collection "as is" without either of these parameters. Output is showing a long list of files in JSON format and other test playbooks work okay. Github is messing up formatting, so please assume I got this laid out right
# main task to export all application log files
- hosts: "isam_appliances"
gather_facts: no
roles:
- role: ibm.isam.export_application_logs
tags: export_application_logs
path: "management_ui"
name: "trace_21.03.17_10.25.52.0.log"
No parameters are passed to the isamapi
...
isamapi:
password: "{{ policyserver_runtime.configuration.ldap_pwd }}"
...
When using the base.install_fixpacks role to apply FixPack, the application is successful, but the execution fails.
TASK [ibm.isam.base.install_fixpacks : Install single fixpack file [fix_pack_file]] ********************************************** fatal: [isva10]: FAILED! => {"ansible_facts": {"activations": ["wga"], "firmware_build": "20231130-1943", "firmware_label": "isva_10.0.7.0_20231130-1943_", "model": "Appliance", "product_description": "IBM Security Verify Access", "product_name": "isva", "version": "10.0.7.0"}, "changed": true, "cmd": "ibmsecurity.isam.base.fixpack.install(isamAppliance=self.isam_server, force=False, file=\"/ibm/isvaansible/./files/10.0.7.0_IF1.fixpack\")", "data": "", "delta": "0:00:21.625787", "end": "2024-04-24 11:23:27.318438", "failed_when_result": true, "rc": 0, "start": "2024-04-24 11:23:05.692651", "status_code": 0, "stdout": "", "stdout_lines": [""]}
After checking the base.install_fixpacks role task, I found a problem with the way the return code is checked.
failed_when: result.rc not in ["0"]
-> failed_when: result.rc not in [0]
Could you please fix this?
I have created a playbook using the execute_pdadmin role. I am able to successfully make most pdadmin commands but when I try to perform a group import it fails. I am able to execute the test command on the isam appliance "group import test cn=test,ou=Groups,cn=Users" but when I attempt via ansible it errors and appears to be parsing the commas. I have attempted multiple iterations and not been able to execute the pdadmin group import via ansible. Has anyone else gotten this to work?
/root/.ansible/collections/ansible_collections/ibm/isam/roles/web/configure_reverseproxy_instances/tasks/main.yml Failed with
"msg": "Failed to template loop_control.label: the inline if-expression on line 1 evaluated to false and no else section was defined."
when inventory use the following template
As a temporary work around, I replaced
label: "{'method': {{ item.1.method }}, inst_name: {{ item.0.inst_name }}, stanza_id: {{ item.1.stanza_id }}{{ (', ' + "'entries'" + ': ' + (item.1.entries | join(''))) if item.1.entries is defined }}{{ (', ' + "'entry_id'" + ': ' + item.1.entry_id) if item.1.entry_id is defined }}{{ (', ' + "'value_id'" + ': ' + item.1.value_id) if item.1.value_id is defined }}}"
with
label: "{'method': {{ item.1.method }}, inst_name: {{ item.0.inst_name }}, stanza_id: {{ item.1.stanza_id }}{{ (', ' + "'entries'" + ': ' + (item.1.entries | join(''))) if item.1.entries is defined }}}"
Trying to configure a few settings using ansible as part of setting up enhanced pwd policy in a PoC environment and it's not working. Not clear why, anyone able to help please :-) No errors, the step is just skipped, suggesting some parameter is missing, however there is nothing in debug output using -vvv in Ansible to provide any clues! I've tried indenting entries and the entries underneath it indented again .. There's no errors, the step is just skipped as if something is missing or it's already been executed, except it hasn't!
Configure ISAM for enhanced PWD policy
name: Configuring ISAM enhanced pwd policy
hosts: isam_appliances
gather_facts: no
roles:
role: ibm.isam.web.configure_runtime_components
tags: configure_runtime_components
policy_server_runtime:
entries:
- { method: update, resource_id: "ivmgrd.conf", stanza_id: "ldap", entry_id: "enhanced-pwd-policy", value_id: "yes" }
- { method: update, resource_id: "ivmgrd.conf", stanza_id: "ldap", entry_id: "auth-using-compare", value_id: "no" }
- { method: update, resource_id: "ldap.conf", stanza_id: "ldap-generic-general", entry_id: "auth-using-compare-supported", value_id: "no" }
when: sec_master_pwd is defined and sec_master_id is defined
Hello,
When I configure Redis with role web/config_reverseproxy_redis, I noticed following task is not executed because passed in instance variable is not the content from _instances although _instances itself is correct:
This is because instances variable is already used in previous tasks and it is not updated in the above task due to variable scope issue I think.
Can you review and validate to ensure both web/config_reverseproxy_redis and web/configure_reverseproxy_instances works correctly together?
Thanks, could you please have fix to be available asap?
10.85.158.21> ESTABLISH LOCAL CONNECTION FOR USER: root
<10.85.158.21> EXEC /bin/sh -c 'echo ~root && sleep 0'
<10.85.158.21> EXEC /bin/sh -c '( umask 77 && mkdir -p "echo /root/.ansible/tmp
"&& mkdir "echo /root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494
" && echo ansible-tmp-1634671937.5714831-5637-197440173555494="echo /root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494
" ) && sleep 0'
Using module file /root/.ansible/collections/ansible_collections/ibm/isam/plugins/modules/isamadmin.py
<10.85.158.21> PUT /root/.ansible/tmp/ansible-local-5629rqyvc4rk/tmpe637qbon TO /root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494/AnsiballZ_isamadmin.py
<10.85.158.21> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494/ /root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494/AnsiballZ_isamadmin.py && sleep 0'
<10.85.158.21> EXEC /bin/sh -c '/opt/bin/python3 /root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494/AnsiballZ_isamadmin.py && sleep 0'
<10.85.158.21> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494/AnsiballZ_isamadmin.py", line 100, in
_ansiballz_main()
File "/root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494/AnsiballZ_isamadmin.py", line 92, in _ansiballz_main
invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
File "/root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494/AnsiballZ_isamadmin.py", line 40, in invoke_module
runpy.run_module(mod_name='ansible_collections.ibm.isam.plugins.modules.isamadmin', init_globals=dict(_module_fqn='ansible_collections.ibm.isam.plugins.modules.isamadmin', _modlib_path=modlib_path),
File "/opt/lib/python3.9/runpy.py", line 210, in run_module
return _run_module_code(code, init_globals, run_name, mod_spec)
File "/opt/lib/python3.9/runpy.py", line 97, in _run_module_code
_run_code(code, mod_globals, init_globals,
File "/opt/lib/python3.9/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/tmp/ansible_ibm.isam.isamadmin_payload_2wi20nu3/ansible_ibm.isam.isamadmin_payload.zip/ansible_collections/ibm/isam/plugins/modules/isamadmin.py", line 114, in
File "/tmp/ansible_ibm.isam.isamadmin_payload_2wi20nu3/ansible_ibm.isam.isamadmin_payload.zip/ansible_collections/ibm/isam/plugins/modules/isamadmin.py", line 92, in main
File "/tmp/ansible_ibm.isam.isamadmin_payload_2wi20nu3/ansible_ibm.isam.isamadmin_payload.zip/ansible_collections/ibm/isam/plugins/module_utils/isam.py", line 16, in init
File "/tmp/ansible_ibm.isam.isamadmin_payload_2wi20nu3/ansible_ibm.isam.isamadmin_payload.zip/ansible/module_utils/connection.py", line 124, in init
AssertionError: socket_path must be a value
fatal: [10.85.158.21]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n File "/root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494/AnsiballZ_isamadmin.py", line 100, in \n _ansiballz_main()\n File "/root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494/AnsiballZ_isamadmin.py", line 92, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File "/root/.ansible/tmp/ansible-tmp-1634671937.5714831-5637-197440173555494/AnsiballZ_isamadmin.py", line 40, in invoke_module\n runpy.run_module(mod_name='ansible_collections.ibm.isam.plugins.modules.isamadmin', init_globals=dict(_module_fqn='ansible_collections.ibm.isam.plugins.modules.isamadmin', _modlib_path=modlib_path),\n File "/opt/lib/python3.9/runpy.py", line 210, in run_module\n return _run_module_code(code, init_globals, run_name, mod_spec)\n File "/opt/lib/python3.9/runpy.py", line 97, in _run_module_code\n _run_code(code, mod_globals, init_globals,\n File "/opt/lib/python3.9/runpy.py", line 87, in _run_code\n exec(code, run_globals)\n File "/tmp/ansible_ibm.isam.isamadmin_payload_2wi20nu3/ansible_ibm.isam.isamadmin_payload.zip/ansible_collections/ibm/isam/plugins/modules/isamadmin.py", line 114, in \n File "/tmp/ansible_ibm.isam.isamadmin_payload_2wi20nu3/ansible_ibm.isam.isamadmin_payload.zip/ansible_collections/ibm/isam/plugins/modules/isamadmin.py", line 92, in main\n File "/tmp/ansible_ibm.isam.isamadmin_payload_2wi20nu3/ansible_ibm.isam.isamadmin_payload.zip/ansible_collections/ibm/isam/plugins/module_utils/isam.py", line 16, in init\n File "/tmp/ansible_ibm.isam.isamadmin_payload_2wi20nu3/ansible_ibm.isam.isamadmin_payload.zip/ansible/module_utils/connection.py", line 124, in init\nAssertionError: socket_path must be a value\n",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
Is it missing some configuration properties that causes the isam.py behaves this way?
custom filters need to use FQCN syntax in collections
I'm attempting to run the extract_certificates playbook:
ansible-playbook -i ./inventory/hosts /home/ansible-user/isam-ansible-collection-master/playbooks/base/extract_certificates.yml
my host_vars/isva-1.yml file contains:
[...]
extract_certificates:
- kdb_id: "{{ pdsrv.kdb }}"
cert_id: "{{ 'WebSEAL-Test-Only' }}"
password: "{{ 'pdsrv' }}"
filename: "{{ 'home/automation/inventory'}}/{{ 'webseal.crt' }}"
[...]
When running the playbook, I get the following error:
ERROR! the loop_control
value must be specified as a dictionary and cannot be a variable itself (though it can contain variables)
Implement this fix:
ansible/ansible@a50dcef
merge_vars is not necessary to combine 2 lists of variables.
I have not tried in ansible core but, if you run this in awx/tower since it has stricter requirements, a lot of this fails. I noticed a lot of playbooks and tasks/main.yml files are missing - - - at the top making it auto fail the checks. They also have spaces issues at the playbook level were the roles are design. I haven't looked at all of them but, I noticed in a couple so far. This will cause issues with whoever runs them. https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html
Enable the possiblity to verify ssl connections to lmi.
When initially setting up a fresh appliance, you'll have to disable the ssl verification and there's 2 options:
When evaluating the Ansible collections for ISVA 10.0.5, I noticed our playbooks fail with the following error:
[2022-12-19 10:54:07,253] [PID:93927 TID:140623308458880] [ERROR] [ibmsecurity.appliance.ibmappliance] [_process_response():70] text: {"message":"Parameter is not valid: enableSSLv3"}
msg: '(''HTTP Return code: 400'', ''{"message":"Parameter is not valid: enableSSLv3"}'')'
name: ibmsecurity.isam.base.admin.set
When inspecing the administrator settings in the LMI, I can see that the following setting does not exist:
Enable SSLv3 | False
In 10.0.2 the setting is available, but not in 10.0.5 it seems.
This causes the Ansible playbooks to fail, maybe a check for the ISVA version can be implemented?
I am able to resolve this by deleting the option in: roles/set_admin_cfg/tasks/main.yml
Files like certificates and html files and mapping rules should NEVER be stored in the inventory directory (or even suggested to put it there). There's a bit of potential ambiguity - inventory_dir is not a full path. The default would then be a directory in the current dir , with the name of the inventory. This could be your actual inventory directory (and that is really wrong).
Unfortunately, a number of roles in this collection do just that.
The current workaround is to override the inventory_dir variable.
I will remove the dependency on inventory_dir in the near future, because it's just a wrong default value.
This handler always times out and does not actuall check anything
A better approach is to have the ansible host actually check if the LMI responds (initial delay of 30 and then a check every 10 seconds)
wait_for:
host: "{{ inventory_hostname }}"
port: "{{ lmi_port }}"
delay: 30
sleep: 10
timeout: "{{ start_config_wait_time }}"
delegate_to: localhost
when: not ansible_check_mode
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.