pax_global_header 0000666 0000000 0000000 00000000064 14600563364 0014521 g ustar 00root root 0000000 0000000 52 comment=7a9ea832a19d7f02d63b356f197453e415bef9da
ansible-freeipa-master/ 0000775 0000000 0000000 00000000000 14600563364 0015404 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/.ansible-lint 0000664 0000000 0000000 00000002302 14600563364 0017763 0 ustar 00root root 0000000 0000000 ---
exclude_paths:
- .ansible-freeipa-tests/
- .cache/
- .github/
- .pre-commit-config.yaml
- .tox/
- .venv/
- .yamllint
- molecule/
- tests/azure/
- meta/runtime.yml
- requirements-docker.yml
- requirements-podman.yml
kinds:
- playbook: '**/tests/**/test_*.yml'
- playbook: '**/playbooks/**/*.yml'
- playbook: '**/tests/ca-less/install_*_without_ca.yml'
- playbook: '**/tests/ca-less/clean_up_certificates.yml'
- playbook: '**/tests/external-signed-ca-with-automatic-copy/install-server-with-external-ca-with-automatic-copy.yml'
- playbook: '**/tests/external-signed-ca-with-manual-copy/install-server-with-external-ca-with-manual-copy.yml'
- playbook: '**/tests/user/create_users_json.yml'
- tasks: '**/tasks_*.yml'
- tasks: '**/env_*.yml'
parseable: true
quiet: false
skip_list:
- '301' # Commands should not change things if nothing needs doing'
- '305' # Use shell only when shell functionality is required
- '306' # risky-shell-pipe
- yaml # yamllint should be executed separately.
- experimental # Do not run any experimental tests
- name[template] # Allow Jinja templating inside task names
- var-naming
use_default_rules: true
verbosity: 1
ansible-freeipa-master/.copr/ 0000775 0000000 0000000 00000000000 14600563364 0016425 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/.copr/Makefile 0000664 0000000 0000000 00000000410 14600563364 0020060 0 ustar 00root root 0000000 0000000 srpm:
# Setup development environment
echo "Installing base development environment"
dnf install -y dnf-plugins-core git-all
echo "Call SRPM build Script"
./utils/build-srpm.sh
if [[ "${outdir}" != "" ]]; then \
mv /builddir/build/SRPMS/* ${outdir}; \
fi
ansible-freeipa-master/.github/ 0000775 0000000 0000000 00000000000 14600563364 0016744 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/.github/workflows/ 0000775 0000000 0000000 00000000000 14600563364 0021001 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/.github/workflows/ansible-test.yml 0000664 0000000 0000000 00000000462 14600563364 0024120 0 ustar 00root root 0000000 0000000 ---
name: ansible-test sanity
on:
- push
- pull_request
jobs:
ansible_test:
name: Verify ansible-test sanity
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
with:
fetch-depth: 0
- name: Run ansible-test
run: bash tests/sanity/sanity.sh
ansible-freeipa-master/.github/workflows/docs.yml 0000664 0000000 0000000 00000004407 14600563364 0022461 0 ustar 00root root 0000000 0000000 ---
name: Verify Ansible documentation.
on:
- push
- pull_request
jobs:
check_docs_oldest_supported:
name: Check Ansible Documentation with ansible-core 2.13.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
with:
fetch-depth: 0
- uses: actions/setup-python@v4.3.0
with:
python-version: '3.x'
- name: Install Ansible 2.13
run: |
python -m pip install "ansible-core >=2.13,<2.14"
- name: Run ansible-doc-test
run: |
ANSIBLE_LIBRARY="." ANSIBLE_DOC_FRAGMENT_PLUGINS="." python utils/ansible-doc-test -v roles plugins
check_docs_previous:
name: Check Ansible Documentation with ansible-core 2.14.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
with:
fetch-depth: 0
- uses: actions/setup-python@v4.3.0
with:
python-version: '3.x'
- name: Install Ansible 2.14
run: |
python -m pip install "ansible-core >=2.14,<2.15"
- name: Run ansible-doc-test
run: |
ANSIBLE_LIBRARY="." ANSIBLE_DOC_FRAGMENT_PLUGINS="." python utils/ansible-doc-test -v roles plugins
check_docs_current:
name: Check Ansible Documentation with ansible-core 2.15.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
with:
fetch-depth: 0
- uses: actions/setup-python@v4.3.0
with:
python-version: '3.x'
- name: Install Ansible 2.15
run: |
python -m pip install "ansible-core >=2.15,<2.16"
- name: Run ansible-doc-test
run: |
ANSIBLE_LIBRARY="." ANSIBLE_DOC_FRAGMENT_PLUGINS="." python utils/ansible-doc-test -v roles plugins
check_docs_ansible_latest:
name: Check Ansible Documentation with latest Ansible version.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
with:
fetch-depth: 0
- uses: actions/setup-python@v4.3.0
with:
python-version: '3.x'
- name: Install Ansible-latest
run: |
python -m pip install ansible
- name: Run ansible-doc-test
run: |
ANSIBLE_LIBRARY="." ANSIBLE_DOC_FRAGMENT_PLUGINS="." python utils/ansible-doc-test -v roles plugins
ansible-freeipa-master/.github/workflows/lint.yml 0000664 0000000 0000000 00000004250 14600563364 0022473 0 ustar 00root root 0000000 0000000 ---
name: Run Linters
on:
- push
- pull_request
jobs:
ansible_lint:
name: Verify ansible-lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
with:
fetch-depth: 0
- uses: actions/setup-python@v4.3.0
with:
python-version: "3.x"
- name: Run ansible-lint
run: |
pip install "ansible-core>=2.16,<2.17" 'ansible-lint>=6.22'
utils/build-galaxy-release.sh -ki
cd .galaxy-build
ansible-lint --profile production --exclude tests/integration/ --exclude tests/unit/ --parseable --nocolor
yamllint:
name: Verify yamllint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
with:
fetch-depth: 0
- uses: actions/setup-python@v4.3.0
with:
python-version: "3.x"
- name: Run yaml-lint
uses: ibiqlik/action-yamllint@v3.1.1
pydocstyle:
name: Verify pydocstyle
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
with:
fetch-depth: 0
- uses: actions/setup-python@v4.3.0
with:
python-version: "3.x"
- name: Run pydocstyle
run: |
pip install pydocstyle
pydocstyle
flake8:
name: Verify flake8
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
with:
fetch-depth: 0
- uses: actions/setup-python@v4.3.0
with:
python-version: "3.x"
- name: Run flake8
run: |
pip install flake8 flake8-bugbear
flake8
pylint:
name: Verify pylint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
with:
fetch-depth: 0
- uses: actions/setup-python@v4.3.0
with:
python-version: "3.x"
- name: Run pylint
run: |
pip install 'pylint>=3.0'
pylint plugins roles --disable=import-error
shellcheck:
name: Shellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
with:
fetch-depth: 0
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@master
ansible-freeipa-master/.github/workflows/readme.yml 0000664 0000000 0000000 00000000715 14600563364 0022764 0 ustar 00root root 0000000 0000000 ---
name: readme test
on:
- push
- pull_request
jobs:
ansible_test:
name: Verify readme
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.1.0
with:
fetch-depth: 0
- name: Run readme test
run: |
error=0
for i in roles/ipa*/README.md README-*.md; do grep -q $i README.md && echo "OK: $i" || { echo -e "\033[31;1mERROR: ${i} missing\033[0m"; error=1; } done
exit $error
ansible-freeipa-master/.gitignore 0000664 0000000 0000000 00000000260 14600563364 0017372 0 ustar 00root root 0000000 0000000 *.pyc
*.retry
*.swp
# collection files
freeipa-ansible_freeipa*.tar.gz
redhat-rhel_idm*.tar.gz
importer_result.json
# ignore virtual environments
/.tox/
/.venv/
tests/logs/
ansible-freeipa-master/.pre-commit-config.yaml 0000664 0000000 0000000 00000002470 14600563364 0021670 0 ustar 00root root 0000000 0000000 ---
repos:
- repo: https://github.com/ansible/ansible-lint.git
rev: v6.22.0
hooks:
- id: ansible-lint
always_run: false
pass_filenames: true
files: \.(yaml|yml)$
exclude: /env[^/]*.(yaml|yml)$
entry: |-
env
ANSIBLE_LIBRARY=./plugins/modules
ANSIBLE_MODULE_UTILS=./plugins/module_utils
ANSIBLE_DOC_FRAGMENT_PLUGINS=./plugins/doc_fragments
ansible-lint
--offline
--profile production
--exclude tests/integration/
--exclude tests/unit/
--parseable
--nocolor
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.32.0
hooks:
- id: yamllint
files: \.(yaml|yml)$
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
- repo: https://github.com/pycqa/pydocstyle
rev: 6.0.0
hooks:
- id: pydocstyle
- repo: https://github.com/pycqa/pylint
rev: v3.0.2
hooks:
- id: pylint
args:
- --disable=import-error
files: \.py$
- repo: local
hooks:
- id: ansible-doc-test
name: Verify Ansible roles and module documentation.
language: python
entry: utils/ansible-doc-test
# args: ['-v', 'roles', 'plugins']
files: ^.*.py$
- repo: local
hooks:
- id: shellcheck
name: ShellCheck
language: system
entry: shellcheck
files: \.sh$
ansible-freeipa-master/.yamllint 0000664 0000000 0000000 00000000552 14600563364 0017240 0 ustar 00root root 0000000 0000000 ---
ignore: |
/.tox/
/.venv/
/.github/
extends: default
rules:
braces:
max-spaces-inside: 1
level: error
brackets:
max-spaces-inside: 1
level: error
truthy:
allowed-values: ["yes", "no", "true", "false", "True", "False"]
level: error
line-length:
max: 160
# Disabled rules
indentation: disable
comments: disable
ansible-freeipa-master/CONTRIBUTING.md 0000664 0000000 0000000 00000010454 14600563364 0017641 0 ustar 00root root 0000000 0000000 Contributing to ansible-freeipa
===============================
As part of the [FreeIPA] project, ansible-freeipa follows
[FreeIPA's Code of Conduct].
Reporting bugs or Features
--------------------------
ansible-freeipa uses [Github issues] for the upstream development, so all RFEs
and bug reports should be added there.
If you have questions about the usage of ansible-freeipa modules and roles,
you should also submit an issue, so that anyone that knows an answer can help.
Development
-----------
Contribute code by submitting a [pull request]. All pull requests should be
created against the `master` branch. If your PR fixes an open issue, please,
add this information to the commit message, like _"Fix issue #num"_.
Every PR will have to pass some automatic checks and be reviewed by another
developer(s). Once they are approved, they will be merged.
In your commits, use clear messages that include intent, summary of changes,
and expected result. Use a template commit message [for modules] and
[for roles].
Upon review, it is fine to `force push` the changes.
**Preparing the development environment**
There are some useful tools that will help you develop for ansible-freeipa,
and you should install, at least, the modules in `requirements.txt`. You
can install the modules with your distribution package manager, or use pip,
as in the example:
```
python3 -m pip install --user -r requirements-dev.txt
```
We recommend using [pre-commit] so that the basic checks that will be executed
for your PR are executed locally, on your commits. To setup the pre-commit
hooks, issue the command:
```
pre-commit install
```
**Developing new modules**
When developing new modules use the script `utils/new_module`. If the module
should have `action: member` support, use the flag `-m`.
This script will create the basic structure for the module, the required files
for tests, playbooks, documentation and source code, all at the appropriate
places.
**Other helpfull tools**
Under directory `utils`, you will find other useful tools, like
**lint-check.sh**, which will run the Python and YAML linters on your code,
and **ansible-doc-test** which will verify if the documentation added to the
roles and modules source code has the right format.
Testing
-------
When testing ansible-freeipa's roles and modules, we aim to check if they
do what they intend to do, report the results correctly, and if they are
idempotent (although, sometimes the operation performed is not, like when
renaming items). To achieve this, we use Ansible playbooks.
The Ansible playbooks test can be found under the [tests] directory. They
should test the behavior of the module or role, and, if possible, provide
test cases for all attributes.
There might be some limitation on the testing environment, as some attributes
or operations are only available in some circumstances, like specific FreeIPA
versions, or some more elaborate scenarios (for example, requiring a
configured trust to an AD domain). For these cases, there are some `facts`
available that will only enable the tests if the testing environment is
enabled.
The tests run automatically on every pull request, using Fedora, CentOS 7,
and CentOS 8 environments.
See the document [Running the tests] and also the section `Preparing the
development environment`, to prepare your environment.
Documentation
-------------
We do our best to provide a correct and complete documentation for the modules
and roles we provide, but we sometimes miss something that users find it
important to be documented.
If you think something could be made easier to understand, or found an error
or omission in the documentation, fixing it will help other users and make
the experience on using the project much better.
Also, the [playbooks] can be seen as part of the documentation, as they are
examples of commonly performed tasks.
---
[FreeIPA]: https://freeipa.org
[FreeIPA's Code of Conduct]: https://github.com/freeipa/freeipa/blob/master/CODE_OF_CONDUCT.md
[for modules]: https://github.com/freeipa/ansible-freeipa/pull/357
[for roles]: https://github.com/freeipa/ansible-freeipa/pull/430
[Github issues]: https://github.com/freeipa/ansible-freeipa/issues
[pull request]: https://github.com/freeipa/ansible-freeipa/pulls
[playbooks]: playbooks
[pre-commit]: https://pre-commit.com
[Running the tests]: tests/README.md
[tests]: tests/
ansible-freeipa-master/COPYING 0000664 0000000 0000000 00000104513 14600563364 0016443 0 ustar 00root root 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
.
ansible-freeipa-master/README-automember.md 0000664 0000000 0000000 00000017067 14600563364 0021034 0 ustar 00root root 0000000 0000000 Automember module
===========
Description
-----------
The automember module allows to ensure presence or absence of automember rules and manage automember rule conditions.
Features
--------
* Automember management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaautomember module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure group automember rule is present with no conditions.
```yaml
---
- name: Playbook to ensure a group automember rule is present with no conditions
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
name: admins
description: "my automember rule"
automember_type: group
```
Example playbook to make sure group automember rule is present with conditions:
```yaml
---
- name: Playbook to add a group automember rule with two conditions
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
name: admins
description: "my automember rule"
automember_type: group
inclusive:
- key: mail
expression: '@example.com$'
exclusive:
- key: uid
expression: "1234"
```
Example playbook to delete a group automember rule:
```yaml
- name: Playbook to delete a group automember rule
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
name: admins
description: "my automember rule"
automember_type: group
state: absent
```
Example playbook to add an inclusive condition to an existing rule
```yaml
- name: Playbook to add an inclusive condition to an existing rule
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
name: "My domain hosts"
description: "my automember condition"
automember_type: hostgroup
action: member
inclusive:
- key: fqdn
expression: ".*.mydomain.com"
```
Example playbook to ensure group membership for all users has been rebuilt
```yaml
- name: Playbook to ensure group membership for all users has been rebuilt
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: group
state: rebuilt
```
Example playbook to ensure group membership for given users has been rebuilt
```yaml
- name: Playbook to ensure group membership for given users has been rebuilt
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
users:
- user1
- user2
state: rebuilt
```
Example playbook to ensure hostgroup membership for all hosts has been rebuilt
```yaml
- name: Playbook to ensure hostgroup membership for all hosts has been rebuilt
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: hostgroup
state: rebuilt
```
Example playbook to ensure hostgroup membership for given hosts has been rebuilt
```yaml
- name: Playbook to ensure hostgroup membership for given hosts has been rebuilt
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
hosts:
- host1.mydomain.com
- host2.mydomain.com
state: rebuilt
```
Example playbook to ensure default group fallback_group for all unmatched group entries is set
```yaml
- name: Playbook to ensure default group fallback_group for all unmatched group entries is set
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: group
default_group: fallback_group
```
Example playbook to ensure default group for all unmatched group entries is not set
```yaml
- name: Playbook to ensure default group for all unmatched group entries is not set
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
default_group: ""
automember_type: group
state: absent
```
Example playbook to ensure default hostgroup fallback_hostgroup for all unmatched group entries
```yaml
- name: Playbook to ensure default hostgroup fallback_hostgroup for all unmatched group entries
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: hostgroup
default_group: fallback_hostgroup
```
Example playbook to ensure default hostgroup for all unmatched group entries is not set
```yaml
- name: Playbook to ensure default hostgroup for all unmatched group entries is not set
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: hostgroup
default_group: ""
state: absent
```
Example playbook to ensure all orphan automember group rules are removed:
```yaml
- name: Playbook to ensure all orphan automember group rules are removed
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: group
state: orphans_removed
```
Example playbook to ensure all orphan automember hostgroup rules are removed:
```yaml
- name: Playbook to ensure all orphan automember hostgroup rules are removed
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: hostgroup
state: orphans_removed
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | Automember rule. | yes
`description` | A description of this auto member rule. | no
`automember_type` | Grouping to which the rule applies. It can be one of `group`, `hostgroup`. | yes
`inclusive` | List of dictionaries in the format of `{'key': attribute, 'expression': inclusive_regex}` | no
`exclusive` | List of dictionaries in the format of `{'key': attribute, 'expression': exclusive_regex}` | no
`users` | Users to rebuild membership for. | no
`hosts` | Hosts to rebuild membership for. | no
`no_wait` | Don't wait for rebuilding membership. | no
`default_group` | Default (fallback) group for all unmatched entries. Use the empty string "" for ensuring the default group is not set. | no
`action` | Work on automember or member level. It can be one of `member` or `automember` and defaults to `automember`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, 'rebuilt'. 'orphans_removed' default: `present`. | no
Authors
=======
Mark Hahl
Thomas Woerner
ansible-freeipa-master/README-automountkey.md 0000664 0000000 0000000 00000005147 14600563364 0021434 0 ustar 00root root 0000000 0000000 Automountkey module
=====================
Description
-----------
The automountkey module allows management of keys within an automount map.
It is desgined to follow the IPA api as closely as possible while ensuring ease of use.
Features
--------
* Automount key management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaautomountkey module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to ensure presence of an automount key:
```yaml
---
- name: Playbook to manage automount key
hosts: ipaserver
tasks:
- name: ensure automount key TestKey is present
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
mapname: TestMap
key: TestKey
info: 192.168.122.1:/exports
state: present
```
Example playbook to rename an automount map:
```yaml
---
- name: Playbook to add an automount map
hosts: ipaserver
tasks:
- name: ensure aumount key TestKey is renamed to NewKeyName
ipaautomountkey:
ipaadmin_password: password01
automountlocationcn: TestLocation
automountmapname: TestMap
automountkey: TestKey
newname: NewKeyName
state: renamed
```
Example playbook to ensure an automount key is absent:
```yaml
---
- name: Playbook to manage an automount key
hosts: ipaserver
tasks:
- name: ensure automount key TestKey is absent
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
mapname: TestMap
key: TestKey
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`location` \| `automountlocationcn` \| `automountlocation` | Location name. | yes
`mapname` \| `map` \| `automountmapname` \| `automountmap` | Map the key belongs to | yes
`key` \| `name` \| `automountkey` | Automount key to manage | yes
`rename` \| `new_name` \| `newautomountkey` | the name to change the key to if state is `renamed` | yes when state is `renamed`
`info` \| `information` \| `automountinformation` | Mount information for the key | yes when state is `present`
`state` | The state to ensure. It can be one of `present`, `absent` or `renamed`, default: `present`. | no
Authors
=======
Chris Procter
ansible-freeipa-master/README-automountlocation.md 0000664 0000000 0000000 00000005066 14600563364 0022454 0 ustar 00root root 0000000 0000000 Automountlocation module
=====================
Description
-----------
The automountlocation module allows the addition and removal of locations for automount maps
It is desgined to follow the IPA api as closely as possible while ensuring ease of use.
Features
--------
* Automount location management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaautomountlocation module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to ensure presence of an automount location:
```yaml
---
- name: Playbook to add an automount location
hosts: ipaserver
become: true
tasks:
- name: ensure a automount location named DMZ exists
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: DMZ
state: present
```
Example playbook to ensure presence of multiple automount locations:
```yaml
---
- name: Playbook to add an automount location
hosts: ipaserver
become: true
tasks:
- name: ensure a automount location named DMZ exists
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name:
- DMZ
- PROD
- development
- test
state: present
```
Example playbook to ensure absence of an automount location:
```yaml
---
- name: Playbook to ensure an automount location is absent
hosts: ipaserver
become: true
tasks:
- name: ensure automount locations LOCATION1 and LOCATION2 do not exist
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name:
- LOCATION1
- LOCATION2
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` \| `location` | List of one or more automountlocation names. | yes
`state` | The state to ensure. It can be one of `present`, or `absent`, default: `present`. | no
Authors
=======
Chris Procter
ansible-freeipa-master/README-automountmap.md 0000664 0000000 0000000 00000005573 14600563364 0021424 0 ustar 00root root 0000000 0000000 Automountmap module
=====================
Description
-----------
The automountmap module allows the addition and removal of maps within automount locations.
It is desgined to follow the IPA api as closely as possible while ensuring ease of use.
Features
--------
* Automount map management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaautomountmap module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to ensure presence of an automount map:
```yaml
---
- name: Playbook to add an automount map
hosts: ipaserver
become: no
tasks:
- name: ensure map named auto.DMZ in location DMZ is created
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: auto.DMZ
location: DMZ
desc: "this is a map for servers in the DMZ"
```
Automount maps can contain a submount key, which defines a mount location within the map the references another map. On FreeIPA, this is known as an indirect map. An indirect automount map is equivalent to adding a proper automount key to a map, referencyng another map (this second map is the indirect map). Use `parent` and `mount` parameters to create an indirect automount map with ansible-freeipa, without the need to directly manage the automount keys.
Example playbook to ensure an indirect automount map is present:
```yaml
---
- name: Playbook to add an indirect automount map
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: auto.indirect
location: DMZ
parent: auto.DMZ
mount: dmz_indirect
```
Example playbook to ensure auto.DMZi is absent:
```yaml
---
- name: Playbook to remove an automount map
hosts: ipaserver
become: no
tasks:
- name: ensure map auto.DMZ has been removed
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: auto.DMZ
location: DMZ
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`name` \| `mapname` \| `map` \| `automountmapname` | Name of the map to manage | yes
`location` \| `automountlocation` \| `automountlocationcn` | Location name. | yes
`parentmap` | Parent map of the indirect map. Can only be used when creating new maps. Default: auto.master | no
`mount` | Indirect map mount point, relative to parent map. | yes, if `parent` is used.
`desc` \| `description` | Description of the map | yes
`state` | The state to ensure. It can be one of `present`, or `absent`, default: `present`. | no
Authors
=======
- Chris Procter
- Rafael Jeffman
ansible-freeipa-master/README-cert.md 0000664 0000000 0000000 00000014662 14600563364 0017627 0 ustar 00root root 0000000 0000000 Cert module
============
Description
-----------
The cert module makes it possible to request, revoke and retrieve SSL certificates for hosts, services and users.
Features
--------
* Certificate request
* Certificate hold/release
* Certificate revocation
* Certificate retrieval
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipacert module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
* Some tool to generate a certificate signing request (CSR) might be needed, like `openssl`.
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to request a new certificate for a service:
```yaml
---
- name: Certificate request
hosts: ipaserver
tasks:
- name: Request a certificate for a web server
ipacert:
ipaadmin_password: SomeADMINpassword
state: requested
csr: |
-----BEGIN CERTIFICATE REQUEST-----
MIGYMEwCAQAwGTEXMBUGA1UEAwwOZnJlZWlwYSBydWxlcyEwKjAFBgMrZXADIQBs
HlqIr4b/XNK+K8QLJKIzfvuNK0buBhLz3LAzY7QDEqAAMAUGAytlcANBAF4oSCbA
5aIPukCidnZJdr491G4LBE+URecYXsPknwYb+V+ONnf5ycZHyaFv+jkUBFGFeDgU
SYaXm/gF8cDYjQI=
-----END CERTIFICATE REQUEST-----
principal: HTTP/www.example.com
register: cert
```
Example playbook to revoke an existing certificate:
```yaml
---
- name: Revoke certificate
hosts: ipaserver
tasks:
- name Revoke a certificate
ipacert:
ipaadmin_password: SomeADMINpassword
serial_number: 123456789
reason: 5
state: revoked
```
When revoking a certificate a mnemonic can also be used to set the revocation reason:
```yaml
---
- name: Revoke certificate
hosts: ipaserver
tasks:
- name Revoke a certificate
ipacert:
ipaadmin_password: SomeADMINpassword
serial_number: 123456789
reason: cessationOfOperation
state: revoked
```
Example to hold a certificate (alias for revoking a certificate with reason `certificateHold (6)`):
```yaml
---
- name: Hold a certificate
hosts: ipaserver
tasks:
- name: Hold certificate
ipacert:
ipaadmin_password: SomeADMINpassword
serial_number: 0xAB1234
state: held
```
Example playbook to release hold of certificate (may be used with any revoked certificates, despite of the rovoke reason):
```yaml
---
- name: Release hold
hosts: ipaserver
tasks:
- name: Take a revoked certificate off hold
ipacert:
ipaadmin_password: SomeADMINpassword
serial_number: 0xAB1234
state: released
```
Example playbook to retrieve a certificate and save it to a file in the target node:
```yaml
---
- name: Retriev certificate
hosts: ipaserver
tasks:
- name: Retrieve a certificate and save it to file 'cert.pem'
ipacert:
ipaadmin_password: SomeADMINpassword
certificate_out: cert.pem
state: retrieved
```
ipacert
-------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`csr` | X509 certificate signing request, in PEM format. | yes, if `state: requested`
`principal` | Host/service/user principal for the certificate. | yes, if `state: requested`
`add` \| `add_principal` | Automatically add the principal if it doesn't exist (service principals only). (bool) | no
`profile_id` \| `profile` | Certificate Profile to use | no
`ca` | Name of the issuing certificate authority. | no
`chain` | Include certificate chain in output. (bool) | no
`serial_number` | Certificate serial number. (int) | yes, if `state` is `retrieved`, `held`, `released` or `revoked`.
`revocation_reason` \| `reason` | Reason for revoking the certificate. Use one of the reason strings, or the corresponding value: "unspecified" (0), "keyCompromise" (1), "cACompromise" (2), "affiliationChanged" (3), "superseded" (4), "cessationOfOperation" (5), "certificateHold" (6), "removeFromCRL" (8), "privilegeWithdrawn" (9), "aACompromise" (10) | yes, if `state: revoked`
`certificate_out` | Write certificate (chain if `chain` is set) to this file, on the target node. | no
`state` | The state to ensure. It can be one of `requested`, `held`, `released`, `revoked`, or `retrieved`. `held` is the same as revoke with reason "certificateHold" (6). `released` is the same as `cert-revoke-hold` on IPA CLI, releasing the hold status of a certificate. | yes
Return Values
=============
Values are returned only if `state` is `requested` or `retrieved` and if `certificate_out` is not defined.
Variable | Description | Returned When
-------- | ----------- | -------------
`certificate` | Certificate fields and data. (dict)
Options: | if `state` is `requested` or `retrieved` and if `certificate_out` is not defined
| `certificate` - Issued X509 certificate in PEM encoding. Will include certificate chain if `chain: true`. (list) | always
| `san_dnsname` - X509 Subject Alternative Name. | When DNSNames are present in the Subject Alternative Name extension of the issued certificate.
| `issuer` - X509 distinguished name of issuer. | always
| `subject` - X509 distinguished name of certificate subject. | always
| `serial_number` - Serial number of the issued certificate. (int) | always
| `revoked` - Revoked status of the certificate. (bool) | if certificate was revoked
| `owner_user` - The username that owns the certificate. | if `state: retrieved` and certificate is owned by a user
| `owner_host` - The host that owns the certificate. | if `state: retrieved` and certificate is owned by a host
| `owner_service` - The service that owns the certificate. | if `state: retrieved` and certificate is owned by a service
| `valid_not_before` - Time when issued certificate becomes valid, in GeneralizedTime format (YYYYMMDDHHMMSSZ) | always
| `valid_not_after` - Time when issued certificate ceases to be valid, in GeneralizedTime format (YYYYMMDDHHMMSSZ) | always
Authors
=======
Sam Morris
Rafael Jeffman
ansible-freeipa-master/README-config.md 0000664 0000000 0000000 00000016113 14600563364 0020130 0 ustar 00root root 0000000 0000000 Config module
===========
Description
-----------
The config module allows the setting of global config parameters within IPA. If no parameters are specified it returns the list of all current parameters.
The config module is as compatible as possible to the Ansible upstream `ipa_config` module, but adds many additional parameters
Features
--------
* IPA server configuration management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaconfig module.
Some variables are only supported on newer versions of FreeIPA. Check `Variables` section for details.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to read config options:
```yaml
---
- name: Playbook to handle global config options
hosts: ipaserver
become: true
tasks:
- name: return current values of the global configuration options
ipaconfig:
ipaadmin_password: password
register: result
- name: display default login shell
debug:
msg: '{{ result.config.defaultshell }}'
- name: ensure defaultloginshell and maxusernamelength are set as required
ipaconfig:
ipaadmin_password: password
defaultshell: /bin/bash
maxusername: 64
```
Example playbook to set global configuration options:
```yaml
---
- name: Playbook to ensure some config options are set
hosts: ipaserver
become: true
tasks:
- name: set defaultlogin and maxusername
ipaconfig:
ipaadmin_password: password
defaultlogin: /bin/bash
maxusername: 64
```
Example playbook to enable SID and generate users and groups SIDs:
```yaml
---
- name: Playbook to ensure SIDs are enabled and users and groups have SIDs
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Enable SID and generate users and groups SIDS
ipaconfig:
ipaadmin_password: SomeADMINpassword
enable_sid: yes
add_sids: yes
```
Example playbook to change IPA domain NetBIOS name:
```yaml
---
- name: Playbook to change IPA domain netbios name
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Set IPA domain netbios name
ipaconfig:
ipaadmin_password: SomeADMINpassword
enable_sid: yes
netbios_name: IPADOM
```
Variables
=========
**General Variables:**
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`maxusername` \| `ipamaxusernamelength` | Set the maximum username length (1 to 255) | no
`maxhostname` \| `ipamaxhostnamelength` | Set the maximum hostname length between 64-255. Only usable with IPA versions 4.8.0 and up. | no
`homedirectory` \| `ipahomesrootdir` | Set the default location of home directories | no
`defaultshell` \| `ipadefaultloginshell` | Set the default shell for new users | no
`defaultgroup` \| `ipadefaultprimarygroup` | Set the default group for new users | no
`emaildomain`\| `ipadefaultemaildomain` | Set the default e-mail domain | false
`searchtimelimit` \| `ipasearchtimelimit` | Set maximum amount of time (seconds) for a search -1 to 2147483647 (-1 or 0 is unlimited) | no
`searchrecordslimit` \| `ipasearchrecordslimit` | Set maximum number of records to search -1 to 2147483647 (-1 or 0 is unlimited) | no
`usersearch` \| `ipausersearchfields` | Set list of fields to search when searching for users | no
`groupsearch` \| `ipagroupsearchfields` | Set list of fields to search in when searching for groups | no
`enable_migration` \| `ipamigrationenabled` | Enable migration mode (choices: True, False ) | no
`groupobjectclasses` \| `ipagroupobjectclasses` | Set default group objectclasses (list) | no
`userobjectclasses` \| `ipauserobjectclasses` | Set default user objectclasses (list) | no
`pwdexpnotify` \| `ipapwdexpadvnotify` | Set number of days's notice of impending password expiration (0 to 2147483647) | no
`configstring` \| `ipaconfigstring` | Set extra hashes to generate in password plug-in (choices:`AllowNThash`, `KDC:Disable Last Success`, `KDC:Disable Lockout`, `KDC:Disable Default Preauth for SPNs`). Use `""` to clear this variable. | no
`selinuxusermaporder` \| `ipaselinuxusermaporder`| Set ordered list in increasing priority of SELinux users | no
`selinuxusermapdefault`\| `ipaselinuxusermapdefault` | Set default SELinux user when no match is found in SELinux map rule | no
`pac_type` \| `ipakrbauthzdata` | set default types of PAC supported for services (choices: `MS-PAC`, `PAD`, `nfs:NONE`). Use `""` to clear this variable. | no
`user_auth_type` \| `ipauserauthtype` | set default types of supported user authentication (choices: `password`, `radius`, `otp`, `pkinit`, `hardened`, `idp`, `disabled`, `""`). An additional check ensures that only types can be used that are supported by the IPA version. Use `""` to clear this variable. | no
`domain_resolution_order` \| `ipadomainresolutionorder` | Set list of domains used for short name qualification | no
`ca_renewal_master_server` \| `ipacarenewalmasterserver`| Renewal master for IPA certificate authority. | no
`enable_sid` | New users and groups automatically get a SID assigned. Cannot be deactivated once activated. Requires IPA 4.9.8+. (bool) | no
`netbios_name` | NetBIOS name of the IPA domain. Requires IPA 4.9.8+ and SID generation to be activated. | no
`add_sids` | Add SIDs for existing users and groups. Requires IPA 4.9.8+ and SID generation to be activated. (bool) | no
Return Values
=============
Variable | Description | Returned When
-------- | ----------- | -------------
`config` | config dict
Fields: | No values to configure are specified
| `maxusername` |
| `maxhostname` |
| `homedirectory` |
| `defaultshell` |
| `defaultgroup` |
| `emaildomain` |
| `searchtimelimit` |
| `searchrecordslimit` |
| `usersearch` |
| `groupsearch` |
| `enable_migration` |
| `groupobjectclasses` |
| `userobjectclasses` |
| `pwdexpnotify` |
| `configstring` |
| `selinuxusermapdefault` |
| `selinuxusermaporder` |
| `pac_type` |
| `user_auth_type` |
| `domain_resolution_order` |
| `ca_renewal_master_server` |
| `enable_sid` |
| `netbios_name` |
All returned fields take the same form as their namesake input parameters
Authors
=======
Chris Procter
ansible-freeipa-master/README-delegation.md 0000664 0000000 0000000 00000007125 14600563364 0021001 0 ustar 00root root 0000000 0000000 Delegation module
=================
Description
-----------
The delegation module allows to ensure presence, absence of delegations and delegation attributes.
Features
--------
* Delegation management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipadelegation module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure delegation "basic manager attributes" is present:
```yaml
---
- name: Playbook to manage IPA delegation.
hosts: ipaserver
become: yes
tasks:
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
- employeetype
group: managers
membergroup: employees
```
Example playbook to make sure delegation "basic manager attributes" is absent:
```yaml
---
- name: Playbook to manage IPA delegation.
hosts: ipaserver
become: yes
tasks:
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
state: absent
```
Example playbook to make sure "basic manager attributes" member attributes employeetype and employeenumber are present:
```yaml
---
- name: Playbook to manage IPA delegation.
hosts: ipaserver
become: yes
tasks:
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- employeenumber
- employeetype
action: member
```
Example playbook to make sure "basic manager attributes" member attributes employeetype and employeenumber are absent:
```yaml
---
- name: Playbook to manage IPA delegation.
hosts: ipaserver
become: yes
tasks:
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- employeenumber
- employeetype
action: member
state: absent
```
Example playbook to make sure delegation "basic manager attributes" is absent:
```yaml
---
- name: Playbook to manage IPA delegation.
hosts: ipaserver
become: yes
tasks:
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `aciname` | The list of delegation name strings. | yes
`permission` \| `permissions` | The permission to grant `read`, `read,write`, `write`]. Default is `write`. | no
`attribute` \| `attrs` | The attribute list to which the delegation applies. | no
`membergroup` \| `memberof` | The user group to apply delegation to. | no
`group` | User group ACI grants access to. | no
`action` | Work on delegation or member level. It can be on of `member` or `delegation` and defaults to `delegation`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-dnsconfig.md 0000664 0000000 0000000 00000006623 14600563364 0020642 0 ustar 00root root 0000000 0000000 DNSConfig module
============
Description
-----------
The dnsconfig module allows to modify global DNS configuration.
Features
--------
* Global DNS configuration
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipadnsconfig module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to set global DNS configuration:
```yaml
---
- name: Playbook to handle global DNS configuration
hosts: ipaserver
become: true
tasks:
# Set dnsconfig.
- ipadnsconfig:
forwarders:
- ip_address: 8.8.4.4
- ip_address: 2001:4860:4860::8888
port: 53
forward_policy: only
allow_sync_ptr: yes
```
Example playbook to ensure a global forwarder, with a custom port, is absent:
```yaml
---
- name: Playbook to handle global DNS configuration
hosts: ipaserver
become: true
tasks:
# Ensure global forwarder with a custom port is absent.
- ipadnsconfig:
forwarders:
- ip_address: 2001:4860:4860::8888
port: 53
action: member
state: absent
```
Example playbook to disable global forwarders:
```yaml
---
- name: Playbook to disable global DNS forwarders
hosts: ipaserver
become: true
tasks:
# Disable global forwarders.
- ipadnsconfig:
forward_policy: none
```
Example playbook to change global forward policy:
```yaml
---
- name: Playbook to change global forward policy
hosts: ipaserver
become: true
tasks:
# Disable global forwarders.
- ipadnsconfig:
forward_policy: first
```
Example playbook to disallow synchronization of forward (A, AAAA) and reverse (PTR) records:
```yaml
---
- name: Playbook to disallow reverse synchronization.
hosts: ipaserver
become: true
tasks:
# Disable global forwarders.
- ipadnsconfig:
allow_sync_ptr: no
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no
| `ip_address` - The IPv4 or IPv6 address of the DNS server. | yes
| `port` - The custom port that should be used on this server. | no
`forward_policy` \| `forwardpolicy` | The global forwarding policy. It can be one of `only`, `first`, or `none`. | no
`allow_sync_ptr` | Allow synchronization of forward (A, AAAA) and reverse (PTR) records (bool). | yes
`action` | Work on dnsconfig or member level. It can be one of `member` or `dnsconfig` and defaults to `dnsconfig`. Only `forwarders` can be managed with `action: member`. | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. `absent` can only be used with `action: member` and `forwarders`. | yes
Authors
=======
Rafael Guterres Jeffman
ansible-freeipa-master/README-dnsforwardzone.md 0000664 0000000 0000000 00000007445 14600563364 0021740 0 ustar 00root root 0000000 0000000 Dnsforwardzone module
=====================
Description
-----------
The dnsforwardzone module allows the addition and removal of dns forwarders from the IPA DNS config.
It is desgined to follow the IPA api as closely as possible while ensuring ease of use.
Features
--------
* DNS zone management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipadnsforwardzone module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to ensure presence of a forwardzone to ipa DNS:
```yaml
---
- name: Playbook to handle add a forwarder
hosts: ipaserver
become: true
tasks:
- name: ensure presence of forwardzone with a single forwarder DNS server
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
state: present
name: example.com
forwarders:
- ip_address: 8.8.8.8
forwardpolicy: first
skip_overlap_check: true
- name: ensure the forward zone is disabled
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
name: example.com
state: disabled
- name: ensure presence of forwardzone with multiple forwarder DNS server
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
state: present
name: example.com
forwarders:
- ip_address: 8.8.8.8
- ip_address: 4.4.4.4
- name: ensure presence of another forwarder to any existing ones for example.com
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
state: present
name: example.com
forwarders:
- ip_address: 1.1.1.1
action: member
- name: ensure presence of forwardzone with single forwarder DNS server on non-stardard port
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
state: present
name: example.com
forwarders:
- ip_address: 4.4.4.4
port: 8053
- name: ensure the forward zone is absent
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
name: example.com
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | Zone name (FQDN). | yes if `state` == `present`
`forwarders` \| `idnsforwarders` | Per-zone forwarders. A custom port can be specified for each forwarder. Options | no
| `ip_address`: The forwarder IP address. | yes
| `port`: The forwarder IP port. | no
`forwardpolicy` \| `idnsforwardpolicy` \| `forward_policy` | Per-zone conditional forwarding policy. Possible values are `only`, `first`, `none`. Set to "none" to disable forwarding to global forwarder for this zone. In that case, conditional zone forwarders are disregarded. | no
`skip_overlap_check` | Force DNS zone creation even if it will overlap with an existing zone. Defaults to False. | no
`permission` | Allow DNS Forward Zone to be managed. (bool) | no
`action` | Work on group or member level. It can be on of `member` or `dnsforwardzone` and defaults to `dnsforwardzone`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled` or `disabled`, default: `present`. | yes
Authors
=======
Chris Procter
ansible-freeipa-master/README-dnsrecord.md 0000664 0000000 0000000 00000031745 14600563364 0020656 0 ustar 00root root 0000000 0000000 DNSRecord module
================
Description
-----------
The dnsrecord module allows management of DNS records and is as compatible as possible with the Ansible upstream `ipa_dnsrecord` module, but provide some other features like multiple record management in one execution and support for more DNS record types.
Features
--------
* DNS record management.
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipadnsrecord module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.example.com
```
Example playbook to ensure an AAAA record is present:
```yaml
---
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: example.com
record_type: 'AAAA'
record_value: '::1'
```
Example playbook to ensure an AAAA record is present, with a TTL of 300:
```yaml
---
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: example.com
record_type: 'AAAA'
record_value: '::1'
record_ttl: 300
```
Example playbook to ensure an AAAA record is present, with a reverse PTR record:
```yaml
---
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host02
zone_name: example.com
record_type: 'AAAA'
record_value: 'fd00::0002'
create_reverse: yes
```
Example playbook to ensure a LOC record is present, given its individual attributes:
```yaml
---
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
name: host03
loc_lat_deg: 52
loc_lat_min: 22
loc_lat_sec: 23.000
loc_lat_dir: N
loc_lon_deg: 4
loc_lon_min: 53
loc_lon_sec: 32.00
loc_lon_dir: E
loc_altitude: -2.00
loc_size: 1.00
loc_h_precision: 10000
loc_v_precision: 10
```
Example playbook to ensure multiple DNS records are present:
```yaml
---
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
records:
- name: host02
zone_name: example.com
record_type: A
record_value:
- "{{ ipv4_prefix }}.112"
- "{{ ipv4_prefix }}.122"
- name: host02
zone_name: example.com
record_type: AAAA
record_value: ::1
```
Example playbook to ensure multiple CNAME records are present:
```yaml
---
- name: Ensure that 'host03' and 'host04' have CNAME records.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
records:
- name: host03
cname_hostname: host03.example.com
- name: host04
cname_hostname: host04.example.com
```
Example playbook to ensure NS record is absent:
```yaml
---
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
name: host04
ns_hostname: host04
state: absent
```
Example playbook to ensure LOC record is present, with fields:
```yaml
---
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
name: host04
loc_lat_deg: 52
loc_lat_min: 22
loc_lat_sec: 23.000
loc_lat_dir: N
loc_lon_deg: 4
loc_lon_min: 53
loc_lon_sec: 32.000
loc_lon_dir: E
loc_altitude: -2.00
loc_size: 0.00
loc_h_precision: 10000
loc_v_precision: 10
```
Change value of an existing LOC record:
```yaml
---
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
name: host04
loc_size: 1.00
loc_rec: 52 22 23 N 4 53 32 E -2 0 10000 10
```
Example playbook to ensure multiple A records are present:
```yaml
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
name: host04
a_rec:
- 192.168.122.221
- 192.168.122.222
- 192.168.122.223
- 192.168.122.224
```
Example playbook to ensure A and AAAA records are present, with reverse records (PTR):
```yaml
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
name: host01
a_rec:
- 192.168.122.221
- 192.168.122.222
aaaa_rec:
- fd00:;0001
- fd00::0002
create_reverse: yes
```
Example playbook to ensure multiple A and AAAA records are present, but only A records have reverse records:
```yaml
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
name: host01
a_ip_address: 192.168.122.221
aaaa_ip_address: fd00::0001
a_create_reverse: yes
```
Example playbook to ensure multiple DNS records are absent:
```yaml
---
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
records:
- name: host01
del_all: yes
- name: host02
del_all: yes
- name: host03
del_all: yes
- name: host04
del_all: yes
- name: _ftp._tcp
del_all: yes
- name: _sip._udp
del_all: yes
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`zone_name` \| `dnszone` | The DNS zone name to which DNS record needs to be managed. You can use one global zone name for multiple records. | no
required: true
`records` | The list of dns records dicts. Each `records` dict entry can contain **record variables**. | no
| **Record variables** | no
**Record variables** | Used when defining a single record. | no
`state` | The state to ensure. It can be one of `present` or `absent`, and defaults to `present`. | yes
**Record Variables:**
Variable | Description | Required
-------- | ----------- | --------
`zone_name` \| `dnszone` | The DNS zone name to which DNS record needs to be managed. You can use one global zone name for multiple records. When used on a `records` dict, overrides the global `zone_name`. | yes
`name` \| `record_name` | The DNS record name to manage. | yes
`record_type` | The type of DNS record. Supported values are `A`, `AAAA`, `A6`, `AFSDB`, `CERT`, `CNAME`, `DLV`, `DNAME`, `DS`, `KX`, `LOC`, `MX`, `NAPTR`, `NS`, `PTR`, `SRV`, `SSHFP`, `TLSA`, `TXT`, `URI`, and defaults to `A`. | no
`record_value` | Manage DNS record name with this values. | no
`record_ttl` | Set the TTL for the record. (int) | no
`del_all` | Delete all associated records. (bool) | no
`a_rec` \| `a_record` | Raw A record. | no
`aaaa_rec` \| `aaaa_record` | Raw AAAA record. | no
`a6_rec` \| `a6_record` | Raw A6 record data. | no
`afsdb_rec` \| `afsdb_record` | Raw AFSDB record. | no
`cert_rec` \| `cert_record` | Raw CERT record. | no
`cname_rec` \| `cname_record` | Raw CNAME record. | no
`dlv_rec` \| `dlv_record` | Raw DLV record. | no
`dname_rec` \| `dname_record` | Raw DNAM record. | no
`ds_rec` \| `ds_record` | Raw DS record. | no
`kx_rec` \| `kx_record` | Raw KX record. | no
`loc_rec` \| `loc_record` | Raw LOC record. | no
`mx_rec` \| `mx_record` | Raw MX record. | no
`naptr_rec` \| `naptr_record` | Raw NAPTR record. | no
`ns_rec` \| `ns_record` | Raw NS record. | no
`ptr_rec` \| `ptr_record` | Raw PTR record. | no
`srv_rec` \| `srv_record` | Raw SRV record. | no
`sshfp_rec` \| `sshfp_record` | Raw SSHFP record. | no
`tlsa_rec` \| `tlsa_record` | Raw TLSA record. | no
`txt_rec` \| `txt_record` | Raw TXT record. | no
`uri_rec` \| `uri_record` | Raw URI record. | no
`ip_address` | IP adress for A or AAAA records. Set `record_type` to `A` or `AAAA`. | no
`create_reverse` \| `reverse` | Create reverse records for `A` and `AAAA` record types. There is no equivalent to remove reverse records. (bool) | no
`a_ip_address` | IP adress for A records. Set `record_type` to `A`. | no
`a_create_reverse` | Create reverse records only for `A` records. There is no equivalent to remove reverse records. (bool) | no
`aaaa_ip_address` | IP adress for AAAA records. Set `record_type` `AAAA`. | no
`aaaa_create_reverse` | Create reverse records only for `AAAA` record types. There is no equivalent to remove reverse records. (bool) | no
`a6_data` | A6 record. Set `record_type` to `A6`. | no
`afsdb_subtype` | AFSDB Subtype. Set `record_type` to `AFSDB`. (int) | no
`afsdb_hostname` | AFSDB Hostname. Set `record_type` to `AFSDB`. | no
`cert_type` | CERT Certificate Type. Set `record_type` to `CERT`. (int) | no
`cert_key_tag` | CERT Key Tag. Set `record_type` to `CERT`. (int) | no
`cert_algorithm` | CERT Algorithm. Set `record_type` to `CERT`. (int) | no
`cert_certificate_or_crl` | CERT Certificate or Certificate Revocation List (CRL). Set `record_type` to `CERT`. | no
`cname_hostname` | A hostname which this alias hostname points to. Set `record_type` to `CNAME`. | no
`dlv_key_tag` | DS Key Tag. Set `record_type` to `DLV`. (int) | no
`dlv_algorithm` | DLV Algorithm. Set `record_type` to `DLV`. (int) | no
`dlv_digest_type` | DLV Digest Type. Set `record_type` to `DLV`. (int) | no
`dlv_digest` | DLV Digest. Set `record_type` to `DLV`. | no
`dname_target` | DNAME Target. Set `record_type` to `DNAME`. | no
`ds_key_tag` | DS Key Tag. Set `record_type` to `DS`. (int) | no
`ds_algorithm` | DS Algorithm. Set `record_type` to `DS`. (int) | no
`ds_digest_type` | DS Digest Type. Set `record_type` to `DS`. (int) | no
`ds_digest` | DS Digest. Set `record_type` to `DS`. | no
`kx_preference` | Preference given to this exchanger. Lower values are more preferred. Set `record_type` to `KX`. (int) | no
`kx_exchanger` | A host willing to act as a key exchanger. Set `record_type` to `KX`. | no
`loc_lat_deg` | LOC Degrees Latitude. Set `record_type` to `LOC`. (int) | no
`loc_lat_min` | LOC Minutes Latitude. Set `record_type` to `LOC`. (int) | no
`loc_lat_sec` | LOC Seconds Latitude. Set `record_type` to `LOC`. (float) | no
`loc_lat_dir` | LOC Direction Latitude. Valid values are `N` or `S`. Set `record_type` to `LOC`. (int) | no
`loc_lon_deg` | LOC Degrees Longitude. Set `record_type` to `LOC`. (int) | no
`loc_lon_min` | LOC Minutes Longitude. Set `record_type` to `LOC`. (int) | no
`loc_lon_sec` | LOC Seconds Longitude. Set `record_type` to `LOC`. (float) | no
`loc_lon_dir` | LOC Direction Longitude. Valid values are `E` or `W`. Set `record_type` to `LOC`. (int) | no
`loc_altitude` | LOC Altitude. Set `record_type` to `LOC`. (float) | no
`loc_size` | LOC Size. Set `record_type` to `LOC`. (float) | no
`loc_h_precision` | LOC Horizontal Precision. Set `record_type` to `LOC`. (float) | no
`loc_v_precision` | LOC Vertical Precision. Set `record_type` to `LOC`. (float) | no
`mx_preference` | Preference given to this exchanger. Lower values are more preferred. Set `record_type` to `MX`. (int) | no
`mx_exchanger` | A host willing to act as a mail exchanger. Set `record_type` to `LOC`. | no
`naptr_order` | NAPTR Order. Set `record_type` to `NAPTR`. (int) | no
`naptr_preference` | NAPTR Preference. Set `record_type` to `NAPTR`. (int) | no
`naptr_flags` | NAPTR Flags. Set `record_type` to `NAPTR`. | no
`naptr_service` | NAPTR Service. Set `record_type` to `NAPTR`. | no
`naptr_regexp` | NAPTR Regular Expression. Set `record_type` to `NAPTR`. | no
`naptr_replacement` | NAPTR Replacement. Set `record_type` to `NAPTR`. | no
`ns_hostname` | NS Hostname. Set `record_type` to `NS`. | no
`ptr_hostname` | The hostname this reverse record points to. . Set `record_type` to `PTR`. | no
`srv_priority` | Lower number means higher priority. Clients will attempt to contact the server with the lowest-numbered priority they can reach. Set `record_type` to `SRV`. (int) | no
`srv_weight` | Relative weight for entries with the same priority. Set `record_type` to `SRV`. (int) | no
`srv_port` | SRV Port. Set `record_type` to `SRV`. (int) | no
`srv_target` | The domain name of the target host or '.' if the service is decidedly not available at this domain. Set `record_type` to `SRV`. | no
`sshfp_algorithm` | SSHFP Algorithm. Set `record_type` to `SSHFP`. (int) | no
`sshfp_fp_type` | SSHFP Fingerprint Type. Set `record_type` to `SSHFP`. (int) | no
`sshfp_fingerprint`| SSHFP Fingerprint. Set `record_type` to `SSHFP`. (int) | no
`txt_data` | TXT Text Data. Set `record_type` to `TXT`. | no
`tlsa_cert_usage` | TLSA Certificate Usage. Set `record_type` to `TLSA`. (int) | no
`tlsa_selector` | TLSA Selector. Set `record_type` to `TLSA`. (int) | no
`tlsa_matching_type` | TLSA Matching Type. Set `record_type` to `TLSA`. (int) | no
`tlsa_cert_association_data` | TLSA Certificate Association Data. Set `record_type` to `TLSA`. | no
`uri_target` | Target Uniform Resource Identifier according to RFC 3986. Set `record_type` to `URI`. | no
`uri_priority` | Lower number means higher priority. Clients will attempt to contact the URI with the lowest-numbered priority they can reach. Set `record_type` to `URI`. (int) | no
`uri_weight` | Relative weight for entries with the same priority. Set `record_type` to `URI`. (int) | no
Authors
=======
Rafael Guterres Jeffman
ansible-freeipa-master/README-dnszone.md 0000664 0000000 0000000 00000015756 14600563364 0020357 0 ustar 00root root 0000000 0000000 DNSZone Module
==============
Description
-----------
The dnszone module allows to configure zones in DNS server.
Features
--------
* Add, remove, modify, enable or disable DNS zones.
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by ipadnszone module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
-----
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to create a simple DNS zone:
```yaml
---
- name: dnszone present
hosts: ipaserver
become: true
tasks:
- name: Ensure zone is present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
state: present
```
Example playbook to create a DNS zone with all currently supported variables:
```yaml
---
- name: dnszone present
hosts: ipaserver
become: true
tasks:
- name: Ensure zone is present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_sync_ptr: true
dynamic_update: true
dnssec: true
allow_transfer:
- 1.1.1.1
- 2.2.2.2
allow_query:
- 1.1.1.1
- 2.2.2.2
forwarders:
- ip_address: 8.8.8.8
- ip_address: 8.8.4.4
port: 52
refresh: 3600
retry: 900
expire: 1209600
minimum: 3600
ttl: 60
default_ttl: 90
name_server: ipaserver.test.local.
admin_email: admin.admin@example.com
nsec3param_rec: "1 7 100 0123456789abcdef"
skip_overlap_check: true
skip_nameserver_check: true
state: present
```
Example playbook to disable a zone:
```yaml
---
- name: Playbook to disable DNS zone
hosts: ipaserver
become: true
tasks:
- name: Disable zone.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
state: disabled
```
Example playbook to enable a zone:
```yaml
---
- name: Playbook to enable DNS zone
hosts: ipaserver
become: true
tasks:
- name: Enable zone.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
state: enabled
```
Example playbook to allow per-zone privilege delegation:
```yaml
---
- name: Playbook to enable per-zone privilege delegation
hosts: ipaserver
become: true
tasks:
- name: Enable privilege delegation.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
permission: true
```
Example playbook to remove a zone:
```yaml
---
- name: Playbook to remove DNS zone
hosts: ipaserver
become: true
tasks:
- name: Remove zone.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
state: absent
```
Example playbook to create a zone for reverse DNS lookup, from an IP address:
```yaml
---
- name: dnszone present
hosts: ipaserver
become: true
tasks:
- name: Ensure zone for reverse DNS lookup is present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 192.168.1.2
state: present
```
Note that, on the previous example the zone created with `name_from_ip` might be "1.168.192.in-addr.arpa.", "168.192.in-addr.arpa.", or "192.in-addr.arpa.", depending on the DNS response the system get while querying for zones, and for this reason, when creating a zone using `name_from_ip`, the inferred zone name is returned to the controller, in the attribute `dnszone.name`. Since the zone inferred might not be what a user expects, `name_from_ip` can only be used with `state: present`. To have more control over the zone name, the prefix length for the IP address can be provided.
Example playbook to create a zone for reverse DNS lookup, from an IP address, given the prefix length and displaying the resulting zone name:
```yaml
---
- name: dnszone present
hosts: ipaserver
become: true
tasks:
- name: Ensure zone for reverse DNS lookup is present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 192.168.1.2/24
state: present
register: result
- name: Display inferred zone name.
debug:
msg: "Zone name: {{ result.dnszone.name }}"
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `zone_name` | The zone name string or list of strings. | no
`name_from_ip` | Derive zone name from reverse of IP (PTR). Can only be used with `state: present`. | no
`forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no
| `ip_address` - The IPv4 or IPv6 address of the DNS server. | yes
| `port` - The custom port that should be used on this server. | no
`forward_policy` | The global forwarding policy. It can be one of `only`, `first`, or `none`. | no
`allow_sync_ptr` | Allow synchronization of forward (A, AAAA) and reverse (PTR) records (bool). | no
`state` | The state to ensure. It can be one of `present`, `enabled`, `disabled` or `absent`, default: `present`. | yes
`name_server`| Authoritative nameserver domain name | no
`admin_email`| Administrator e-mail address | no
`update_policy`| BIND update policy | no
`dynamic_update` \| `dynamicupdate` | Allow dynamic updates | no
`dnssec`| Allow inline DNSSEC signing of records in the zone | no
`allow_transfer`| List of IP addresses or networks which are allowed to transfer the zone | no
`allow_query`| List of IP addresses or networks which are allowed to issue queries | no
`refresh`| SOA record refresh time | no
`retry`| SOA record retry time | no
`expire`| SOA record expire time | no
`minimum`| How long should negative responses be cached | no
`ttl`| Time to live for records at zone apex | no
`default_ttl`| Time to live for records without explicit TTL definition | no
`nsec3param_rec`| NSEC3PARAM record for zone in format: hash_algorithm flags iterations salt | no
`permission` \| `managedby` | Set per-zone access delegation permission. | no
`skip_overlap_check`| Force DNS zone creation even if it will overlap with an existing zone | no
`skip_nameserver_check` | Force DNS zone creation even if nameserver is not resolvable | no
Return Values
=============
Variable | Description | Returned When
-------- | ----------- | -------------
`dnszone` | DNS Zone dict with zone name infered from `name_from_ip`.
Options: | If `state` is `present`, `name_from_ip` is used, and a zone was created.
| `name` - The name of the zone created, inferred from `name_from_ip`. | Always
Authors
=======
- Sergio Oliveira Campos
- Thomas Woerner
- Rafael Jeffman
ansible-freeipa-master/README-group.md 0000664 0000000 0000000 00000020011 14600563364 0020007 0 ustar 00root root 0000000 0000000 Group module
============
Description
-----------
The group module allows to ensure presence and absence of groups and members of groups.
The group module is as compatible as possible to the Ansible upstream `ipa_group` module, but additionally offers to add users to a group and also to remove users from a group.
## Note
Ensuring presence (adding) of several groups with mixed types (`external`, `nonposix` and `posix`) requires a fix in FreeIPA. The module implements a workaround to automatically use `client` context if the fix is not present in the target node FreeIPA and if more than one group is provided to the task using the `groups` parameter. If `ipaapi_context` is forced to be `server`, the module will fail in this case.
Features
--------
* Group management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipagroup module.
Some variables are only supported on newer versions of FreeIPA. Check `Variables` section for details.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to add groups:
```yaml
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
# Create group ops with gid 1234
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: ops
gidnumber: 1234
# Create group sysops
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: sysops
user:
- pinky
# Create group appops
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: appops
```
These three `ipagroup` module calls can be combined into one with the `groups` variable:
```yaml
---
- name: Playbook to handle groups
hosts: ipaserver
tasks:
- name: Ensure groups ops, sysops and appops are present
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: ops
gidnumber: 1234
- name: sysops
user:
- pinky
- name: appops
```
You can also alternatively use a json file containing the groups, here `groups_present.json`:
```json
{
"groups": [
{
"name": "group1",
"description": "description group1"
},
{
"name": "group2",
"description": "description group2"
}
]
}
```
And ensure the presence of the groups with this example playbook:
```yaml
---
- name: Tests
hosts: ipaserver
gather_facts: false
tasks:
- name: Include groups_present.json
include_vars:
file: groups_present.json
- name: Groups present
ipagroup:
ipaadmin_password: SomeADMINpassword
groups: "{{ groups }}"
```
Example playbook to rename a group:
```yaml
---
- name: Playbook to rename a single group
hosts: ipaserver
become: false
gather_facts: false
tasks:
- name: Rename group appops to webops
ipagroup:
ipaadmin_password: SomeADMINpassword
name: appops
rename: webops
state: renamed
```
Several groups can also be renamed with a single task, as in the example playbook:
```yaml
---
- name: Playbook to rename multiple groups
hosts: ipaserver
become: false
gather_facts: false
tasks:
- name Rename group1 to newgroup1 and group2 to newgroup2
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: group1
rename: newgroup1
- name: group2
rename: newgroup2
state: renamed
```
Example playbook to add users to a group:
```yaml
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
# Add user member brain to group sysops
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: sysops
action: member
user:
- brain
```
`action` controls if a the group or member will be handled. To add or remove members, set `action` to `member`.
Example playbook to add group members to a group:
```yaml
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
# Add group members sysops and appops to group ops
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: ops
group:
- sysops
- appops
```
Example playbook to add members from a trusted realm to an external group:
```yaml
---
- name: Playbook to handle groups.
hosts: ipaserver
tasks:
- name: Create an external group and add members from a trust to it.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external: yes
externalmember:
- WINIPA\\Web Users
- WINIPA\\Developers
```
Example playbook to add nonposix and external groups:
```yaml
---
- name: Playbook to add nonposix and external groups
hosts: ipaserver
tasks:
- name: Add nonposix group sysops and external group appops
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: sysops
nonposix: true
- name: appops
external: true
```
Example playbook to remove groups:
```yaml
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
# Remove groups sysops, appops and ops
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: sysops,appops,ops
state: absent
```
Example playbook to ensure groups are absent:
```yaml
---
- name: Playbook to handle groups
hosts: ipaserver
tasks:
- name: Ensure groups ops and sysops are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: ops
- name: sysops
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to
. (bool) | no
`name` \| `cn` | The list of group name strings. | no
`groups` | The list of group dicts. Each `groups` dict entry can contain group variables.
There is one required option in the `groups` dict:| no
| `name` - The group name string of the entry. | yes
`description` | The group description string. | no
`gid` \| `gidnumber` | The GID integer. | no
`posix` | Create a non-POSIX group or change a non-POSIX to a posix group. `nonposix`, `posix` and `external` are mutually exclusive. (bool) | no
`nonposix` | Create as a non-POSIX group. `nonposix`, `posix` and `external` are mutually exclusive. (bool) | no
`external` | Allow adding external non-IPA members from trusted domains. `nonposix`, `posix` and `external` are mutually exclusive. (bool) | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`user` | List of user name strings assigned to this group. | no
`group` | List of group name strings assigned to this group. | no
`service` | List of service name strings assigned to this group. Only usable with IPA versions 4.7 and up. | no
`membermanager_user` | List of member manager users assigned to this group. Only usable with IPA versions 4.8.4 and up. | no
`membermanager_group` | List of member manager groups assigned to this group. Only usable with IPA versions 4.8.4 and up. | no
`externalmember` \| `ipaexternalmember` \| `external_member`| List of members of a trusted domain in DOM\\name or name@domain form. | no
`idoverrideuser` | List of user ID overrides to manage. Only usable with IPA versions 4.8.7 and up.| no
`rename` \| `new_name` | Rename the user object to the new name string. Only usable with `state: renamed`. | no
`action` | Work on group or member level. It can be on of `member` or `group` and defaults to `group`. | no
`state` | The state to ensure. It can be one of `present`, `absent` or `renamed`, default: `present`. | yes
Authors
=======
- Thomas Woerner
- Rafael Jeffman
ansible-freeipa-master/README-hbacrule.md 0000664 0000000 0000000 00000010042 14600563364 0020443 0 ustar 00root root 0000000 0000000 HBACrule module
===============
Description
-----------
The hbacrule (HBAC Rule) module allows to ensure presence and absence of HBAC Rules and host, hostgroups, HBAC Services, HBAC Service Groups, users, and user groups as members of HBAC Rule.
Features
--------
* HBAC Rule management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipahbacrule module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure HBAC Rule login exists:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Rule login is present
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: login
```
Example playbook to make sure HBAC Rule login exists with the only HBAC Service sshd:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Rule login is present with the only HBAC Service sshd
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: login
hbacsvc:
- sshd
```
Example playbook to make sure HBAC Service sshd is present in HBAC Rule login:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service sshd is present in HBAC Rule login
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: login
hbacsvc:
- sshd
action: member
```
Example playbook to make sure HBAC Service sshd is absent in HBAC Rule login:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service sshd is present in HBAC Rule login
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: login
hbacsvc:
- sshd
action: member
state: absent
```
Example playbook to make sure HBAC Rule login is absent:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Rule login is present
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: login
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of hbacrule name strings. | yes
`description` | The hbacrule description string. | no
`usercategory` \| `usercat` | User category the rule applies to. Choices: ["all", ""] | no
`hostcategory` \| `hostcat` | Host category the rule applies to. Choices: ["all", ""] | no
`servicecategory` \| `servicecat` | HBAC service category the rule applies to. Choices: ["all", ""] | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`host` | List of host name strings assigned to this hbacrule. | no
`hostgroup` | List of host group name strings assigned to this hbacrule. | no
`hbacsvc` | List of HBAC Service name strings assigned to this hbacrule. | no
`hbacsvcgroup` | List of HBAC Service Group name strings assigned to this hbacrule. | no
`user` | List of user name strings assigned to this hbacrule. | no
`group` | List of user group name strings assigned to this hbacrule. | no
`action` | Work on hbacrule or member level. It can be on of `member` or `hbacrule` and defaults to `hbacrule`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled` or `disabled`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-hbacsvc.md 0000664 0000000 0000000 00000004476 14600563364 0020305 0 ustar 00root root 0000000 0000000 HBACsvc module
==============
Description
-----------
The hbacsvc (HBAC Service) module allows to ensure presence and absence of HBAC Services.
Features
--------
* HBACsvc management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipahbacsvc module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure HBAC Service for http is present
```yaml
---
- name: Playbook to handle HBAC Services
hosts: ipaserver
become: true
tasks:
# Ensure HBAC Service for http is present
- ipahbacsvc:
ipaadmin_password: SomeADMINpassword
name: http
description: Web service
```
Example playbook to make sure HBAC Service for tftp is present
```yaml
---
- name: Playbook to handle HBAC Services
hosts: ipaserver
become: true
tasks:
# Ensure HBAC Service for tftp is present
- ipahbacsvc:
ipaadmin_password: SomeADMINpassword
name: tftp
description: TFTPWeb service
```
Example playbook to make sure HBAC Services for http and tftp are absent
```yaml
---
- name: Playbook to handle HBAC Services
hosts: ipaserver
become: true
tasks:
# Ensure HBAC Service for http and tftp are absent
- ipahbacsvc:
ipaadmin_password: SomeADMINpassword
name: http,tftp
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` \| `service` | The list of hbacsvc name strings. | no
`description` | The hbacsvc description string. | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-hbacsvcgroup.md 0000664 0000000 0000000 00000006745 14600563364 0021363 0 ustar 00root root 0000000 0000000 HBACsvcgroup module
===================
Description
-----------
The hbacsvcgroup (HBAC Service Group) module allows to ensure presence and absence of HBAC Service Groups and members of the groups.
Features
--------
* HBAC Service Group management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipahbacsvcgroup module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure HBAC Service Group login exists:
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service Group login is present
- ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: login
```
Example playbook to make sure HBAC Service Group login exists with the only HBAC Service sshd:
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service Group login is present with the only HBAC Service sshd
- ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: login
hbacsvc:
- sshd
```
Example playbook to make sure HBAC Service sshd is present in HBAC Service Group login:
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service sshd is present in HBAC Service Group login
- ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: login
hbacsvc:
- sshd
action: member
```
Example playbook to make sure HBAC Service sshd is absent in HBAC Service Group login:
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service sshd is present in HBAC Service Group login
- ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: login
hbacsvc:
- sshd
action: member
state: absent
```
Example playbook to make sure HBAC Service Group login is absent:
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service Group login is present
- ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: login
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of hbacsvcgroup name strings. | no
`description` | The hbacsvcgroup description string. | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`hbacsvc` | List of hbacsvc name strings assigned to this hbacsvcgroup. | no
`action` | Work on hbacsvcgroup or member level. It can be on of `member` or `hbacsvcgroup` and defaults to `hbacsvcgroup`. | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-host.md 0000664 0000000 0000000 00000030436 14600563364 0017644 0 ustar 00root root 0000000 0000000 Host module
===========
Description
-----------
The host module allows to ensure presence, absence and disablement of hosts.
The host module is as compatible as possible to the Ansible upstream `ipa_host` module, but additionally offers to disable hosts.
Features
--------
* Host management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipahost module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to ensure host presence:
```yaml
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
# Ensure host is present
- ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
description: Example host
ip_address: 192.168.0.123
locality: Lab
ns_host_location: Lab
ns_os_version: CentOS 7
ns_hardware_platform: Lenovo T61
mac_address:
- "08:00:27:E3:B1:2D"
- "52:54:00:BD:97:1E"
state: present
```
Compared to `ipa host-add` command no IP address conflict check is done as the ipahost module supports to have several IPv4 and IPv6 addresses for a host.
Example playbook to ensure host presence with several IP addresses:
```yaml
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
# Ensure host is present
- ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
description: Example host
ip_address:
- 192.168.0.123
- 192.168.0.124
- fe80::20c:29ff:fe02:a1b3
- fe80::20c:29ff:fe02:a1b4
locality: Lab
ns_host_location: Lab
ns_os_version: CentOS 7
ns_hardware_platform: Lenovo T61
mac_address:
- "08:00:27:E3:B1:2D"
- "52:54:00:BD:97:1E"
state: present
```
Example playbook to ensure IP addresses are present for a host:
```yaml
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
# Ensure host is present
- ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
ip_address:
- 192.168.0.124
- fe80::20c:29ff:fe02:a1b4
action: member
state: present
```
Example playbook to ensure IP addresses are absent for a host:
```yaml
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
# Ensure host is present
- ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
ip_address:
- 192.168.0.124
- fe80::20c:29ff:fe02:a1b4
action: member
state: absent
```
Example playbook to ensure host presence without DNS:
```yaml
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
# Ensure host is present without DNS
- ipahost:
ipaadmin_password: SomeADMINpassword
name: host02.example.com
description: Example host
force: yes
```
Example playbook to ensure host presence with a random password:
```yaml
---
- name: Ensure host with random password
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com present with random password
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
random: yes
force: yes
update_password: on_create
register: ipahost
- name: Print generated random password
debug:
var: ipahost.host.randompassword
```
Please remember that a new random password will be generated for an existing but not enrolled host if `update_password` is not limited to `on_create`. For an already enrolled host the task will fail with `update_password` default setting `always`.
Example playbook to ensure presence of several hosts with a random password:
```yaml
---
- name: Ensure hosts with random password
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.example.com and host01.example.com present with random passwords
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
random: yes
force: yes
update_password: on_create
- name: host02.example.com
random: yes
force: yes
update_password: on_create
register: ipahost
- name: Print generated random password for host01.example.com
debug:
var: ipahost.host["host01.example.com"].randompassword
- name: Print generated random password for host02.example.com
debug:
var: ipahost.host["host02.example.com"].randompassword
```
Please remember that a new random password will be generated for an existing but not enrolled host if `update_password` is not limited to `on_create`. For an already enrolled host the task will fail with `update_password` default setting `always`.
Example playbook to ensure presence of host member principal:
```yaml
---
- name: Host present with principal
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com present with principals host/testhost01.example.com and host/myhost01.example.com
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
principal:
- host/testhost01.example.com
- host/myhost01.example.com
action: member
```
Example playbook to ensure presence of host member certificate:
```yaml
- name: Host present with certificate
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com present with certificate
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
certificate:
- MIIC/zCCAeegAwIBAg...
action: member
```
Example playbook to ensure presence of member managedby_host for serveral hosts:
```yaml
---
- name: Host present with managedby_host
hosts: ipaserver
become: true
tasks:
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
managedby_host: server.example.com
- name: host02.example.com
managedby_host: server.example.com
action: member
```
Example playbook to disable a host:
```yaml
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
# Ensure host is disabled
- ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
update_dns: yes
state: disabled
```
`update_dns` controls if the DNS entries will be updated in this case. For `state` present it is controlling the update of the DNS SSHFP records, but not the the other DNS records.
Example playbook to ensure a host is absent:
```yaml
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
# Ensure host is absent
- ipahost:
ipaadmin_password: password1
name: host01.example.com
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `fqdn` | The list of host name strings. `name` with *host variables* or `hosts` containing *host variables* need to be used. | no
**Host variables** | Only used with `name` variable in the first level. | no
`hosts` | The list of host dicts. Each `hosts` dict entry can contain **host variables**.
There is one required option in the `hosts` dict:| no
| `name` \| `fqdn` - The user name string of the entry. | yes
| **Host variables** | no
`update_password` | Set password for a host in present state only on creation or always. It can be one of `always` or `on_create` and defaults to `always`. | no
`action` | Work on host or member level. It can be on of `member` or `host` and defaults to `host`. | no
`state` | The state to ensure. It can be one of `present`, `absent` or `disabled`, default: `present`. | yes
**Host Variables:**
Variable | Description | Required
-------- | ----------- | --------
`description` | The host description. | no
`locality` | Host locality (e.g. "Baltimore, MD"). | no
`location` \| `ns_host_location` | Host physical location hint (e.g. "Lab 2"). | no
`platform` \| `ns_hardware_platform` | Host hardware platform (e.g. "Lenovo T61"). | no
`os` \| `ns_os_version` | Host operating system and version (e.g. "Fedora 9"). | no
`password` \| `user_password` \| `userpassword` | Password used in bulk enrollment for absent or not enrolled hosts. | no
`random` \| `random_password` | Initiate the generation of a random password to be used in bulk enrollment for absent or not enrolled hosts. | no
`certificate` \| `usercertificate` | List of base-64 encoded host certificates | no
`managedby` \| `principalname` \| `krbprincipalname` | List of hosts that can manage this host | no
`principal` \| `principalname` \| `krbprincipalname` | List of principal aliases for this host | no
`allow_create_keytab_user` \| `ipaallowedtoperform_write_keys_user` | Users allowed to create a keytab of this host. | no
`allow_create_keytab_group` \| `ipaallowedtoperform_write_keys_group` | Groups allowed to create a keytab of this host. | no
`allow_create_keytab_host` \| `ipaallowedtoperform_write_keys_host` | Hosts allowed to create a keytab of this host. | no
`allow_create_keytab_hostgroup` \| `ipaallowedtoperform_write_keys_hostgroup` | Host groups allowed to create a keytab of this host. | no
`allow_retrieve_keytab_user` \| `ipaallowedtoperform_read_keys_user` | Users allowed to retieve a keytab of this host. | no
`allow_retrieve_keytab_group` \| `ipaallowedtoperform_read_keys_group` | Groups allowed to retieve a keytab of this host. | no
`allow_retrieve_keytab_host` \| `ipaallowedtoperform_read_keys_host` | Hosts allowed to retieve a keytab of this host. | no
`allow_retrieve_keytab_hostgroup` \| `ipaallowedtoperform_read_keys_hostgroup` | Host groups allowed to retieve a keytab of this host. | no
`mac_address` \| `macaddress` | List of hardware MAC addresses. | no
`sshpubkey` \| `ipasshpubkey` | List of SSH public keys | no
`userclass` \| `class` | Host category (semantics placed on this attribute are for local interpretation) | no
`auth_ind` \| `krbprincipalauthind` | Defines an allow list for Authentication Indicators. Use 'otp' to allow OTP-based 2FA authentications. Use 'radius' to allow RADIUS-based 2FA authentications. Use empty string to reset auth_ind to the initial value. Other values may be used for custom configurations. An additional check ensures that only types can be used that are supported by the IPA version. Choices: ["radius", "otp", "pkinit", "hardened", "idp", ""] | no
`requires_pre_auth` \| `ipakrbrequirespreauth` | Pre-authentication is required for the service (bool) | no
`ok_as_delegate` \| `ipakrbokasdelegate` | Client credentials may be delegated to the service (bool) | no
`ok_to_auth_as_delegate` \| `ipakrboktoauthasdelegate` | The service is allowed to authenticate on behalf of a client (bool) | no
`force` | Force host name even if not in DNS. | no
`reverse` | Reverse DNS detection. | no
`ip_address` \| `ipaddress` | The host IP address list. It can contain IPv4 and IPv6 addresses. No conflict check for IP addresses is done. | no
`update_dns` | For existing hosts: DNS SSHFP records are updated with `state` present and all DNS entries for a host removed with `state` absent. | no
Return Values
=============
There are only return values if one or more random passwords have been generated.
Variable | Description | Returned When
-------- | ----------- | -------------
`host` | Host dict with random password. (dict)
Options: | If random is yes and host did not exist or update_password is yes
| `randompassword` - The generated random password | If only one host is handled by the module without using the `hosts` parameter.
| `name` - The host name of the host that got a new random password. (dict)
Options:
`randompassword` - The generated random password | If several hosts are handled by the module with the `hosts` parameter.
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-hostgroup.md 0000664 0000000 0000000 00000010604 14600563364 0020714 0 ustar 00root root 0000000 0000000 Hostgroup module
================
Description
-----------
The hostgroup module allows to ensure presence and absence of hostgroups and members of hostgroups.
The hostgroup module is as compatible as possible to the Ansible upstream `ipa_hostgroup` module, but additionally offers to make sure that hosts are present or absent in a hostgroup.
Features
--------
* Hostgroup management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipahostgroup module.
Some variables are only supported on newer versions of FreeIPA. Check `Variables` section for details.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure hostgroup databases exists:
```yaml
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure host-group databases is present
- ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
```
Example playbook to make sure that hosts and hostgroups are present in existing databases hostgroup:
```yaml
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure hosts and hostgroups are present in existing databases hostgroup
- ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
action: member
```
`action` controls if a the hostgroup or member will be handled. To add or remove members, set `action` to `member`.
Example playbook to make sure hosts and hostgroups are absent in databases hostgroup:
```yaml
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure hosts and hostgroups are absent in databases hostgroup
- ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
action: member
state: absent
```
Example playbook to rename an existing playbook:
```yaml
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure host-group databases is absent
- ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
rename: datalake
state: renamed
```
Example playbook to make sure host-group databases is absent:
```yaml
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure host-group databases is absent
- ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of hostgroup name strings. | no
`description` | The hostgroup description string. | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`host` | List of host name strings assigned to this hostgroup. | no
`hostgroup` | List of hostgroup name strings assigned to this hostgroup. | no
`membermanager_user` | List of member manager users assigned to this hostgroup. Only usable with IPA versions 4.8.4 and up. | no
`membermanager_group` | List of member manager groups assigned to this hostgroup. Only usable with IPA versions 4.8.4 and up. | no
`rename` \| `new_name` | Rename hostgroup to the provided name. Only usable with IPA versions 4.8.7 and up. | no
`action` | Work on hostgroup or member level. It can be on of `member` or `hostgroup` and defaults to `hostgroup`. | no
`state` | The state to ensure. It can be one of `present`, `absent` or `renamed`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-idoverridegroup.md 0000664 0000000 0000000 00000013572 14600563364 0022102 0 ustar 00root root 0000000 0000000 Idoverridegroup module
============
Description
-----------
The idoverridegroup module allows to ensure presence and absence of idoverridegroups and idoverridegroup members.
Use Cases
---------
With idoverridegroup it is possible to manage group attributes within ID views. These attributes are for example the group name or gid.
Features
--------
* Idoverridegroup management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaidoverridegroup module.
Requirements
------------
**Controller**
* Ansible version: 2.13
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure test group test_group is present in idview test_idview
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview.
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
```
Example playbook to make sure test group test_group is present in idview test_idview with description
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview with description
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
description: "test_group description"
```
Example playbook to make sure test group test_group is present in idview test_idview without description
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview without description
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
description: ""
```
Example playbook to make sure test group test_group is present in idview test_idview with internal name test_123_group
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview with internal name test_123_group
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
name: test_123_group
```
Example playbook to make sure test group test_group is present in idview test_idview without internal name
```yaml
---
- name: Playbook to manage idoverridegroup
- name: Ensure test group test_group is present in idview test_idview without internal name
hosts: ipaserver
become: false
tasks:
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
name: ""
```
Example playbook to make sure test group test_group is present in idview test_idview with gid 20001
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview with gid 20001
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
gid: 20001
```
Example playbook to make sure test group test_group is present in idview test_idview without gid
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview without gid
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
gid: ""
```
Example playbook to make sure test group test_group is present in idview test_idview with enabling falling back to AD DC LDAP when resolving AD trusted objects. (For two-way trusts only.)
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is present in idview test_idview with fallback_to_ldap enabled
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
fallback_to_ldap: true
```
Example playbook to make sure test group test_group is absent in idview test_idview
```yaml
---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: false
tasks:
- name: Ensure test group test_group is absent in idview test_idview
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
continue: true
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to true. (bool) | no
`idview` \| `idviewcn` | The doverridegroup idview string. | yes
`anchor` \| `ipaanchoruuid` | The list of anchors to override. | yes
`description` \| `desc` | Description | no
`name` \| `group_name` \| `cn` | The group. | no
`gid` \| `gidnumber` | Group ID Number (int or "") | no
`fallback_to_ldap` | Allow falling back to AD DC LDAP when resolving AD trusted objects. For two-way trusts only. | no
`delete_continue` \| `continue` | Continuous mode. Don't stop on errors. Valid only if `state` is `absent`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-idoverrideuser.md 0000664 0000000 0000000 00000031530 14600563364 0021716 0 ustar 00root root 0000000 0000000 Idoverrideuser module
============
Description
-----------
The idoverrideuser module allows to ensure presence and absence of idoverrideusers and idoverrideuser members.
Use Cases
---------
With idoverrideuser it is possible to manage user attributes within ID views. These attributes are for example the login name, home directory, certificate for authentication or SSH keys.
Features
--------
* Idoverrideuser management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaidoverrideuser module.
Requirements
------------
**Controller**
* Ansible version: 2.13
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure test user test_user is present in idview test_idview
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview.
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
```
Example playbook to make sure test user test_user is present in idview test_idview with description
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with description
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
description: "test_user description"
```
Example playbook to make sure test user test_user is present in idview test_idview without description
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without description
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
description: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with internal name test_123_user
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with internal name test_123_user
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
name: test_123_user
```
Example playbook to make sure test user test_user is present in idview test_idview without internal name
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without internal name
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
name: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with uid 20001
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with uid 20001
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
uid: 20001
```
Example playbook to make sure test user test_user is present in idview test_idview without uid
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without uid
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
uid: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with gecos "Gecos Test"
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with gecos "Gecos Test"
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gecos: Gecos Test
```
Example playbook to make sure test user test_user is present in idview test_idview without gecos
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without gecos
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gecos: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with gidnumber
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with gidnumber
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gidnumber: 20001
```
Example playbook to make sure test user test_user is present in idview test_idview without gidnumber
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without gidnumber
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gidnumber: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with homedir /Users
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with homedir /Users
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
homedir: /Users
```
Example playbook to make sure test user test_user is present in idview test_idview without homedir
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without homedir
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
homedir: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with shell
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with shell
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
shell: /bin/someshell
```
Example playbook to make sure test user test_user is present in idview test_idview without shell
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without shell
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
shell: ""
```
Example playbook to make sure test user test_user is present in idview test_idview with sshpubkey
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with sshpubkey
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
sshpubkey:
- ssh-rsa AAAAB3NzaC1yc2EAAADAQABAAABgQCqmVDpEX5gnSjKuv97Ay ...
```
Example playbook to make sure test user test_user is present in idview test_idview without sshpubkey
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without sshpubkey
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
sshpubkey: []
```
Example playbook to make sure test user test_user is present in idview test_idview with 1 certificate
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with 1 certificate
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
```
Example playbook to make sure test user test_user is present in idview test_idview with 3 certificate members
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with 3 certificate members
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
```
Example playbook to make sure test user test_user is present in idview test_idview without 2 certificate members
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without 2 certificate members
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
state: absent
```
Example playbook to make sure test user test_user is present in idview test_idview without certificates
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview without certificates
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate: []
```
Example playbook to make sure test user test_user is present in idview test_idview with enabling falling back to AD DC LDAP when resolving AD trusted objects. (For two-way trusts only.)
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview with fallback_to_ldap enabled
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
fallback_to_ldap: true
```
Example playbook to make sure test user test_user is absent in idview test_idview
```yaml
---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is absent in idview test_idview
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
continue: true
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to true. (bool) | no
`idview` \| `idviewcn` | The doverrideuser idview string. | yes
`anchor` \| `ipaanchoruuid` | The list of anchors to override. | yes
`description` \| `desc` | Description | no
`name` \| `login` | The user (internally uid) | no
`uid` \| `uidnumber` | User ID Number (int or "") | no
`gecos` | GECOS | no
`gidnumber` | Group ID Number (int or ""). | no
`homedir` \| `homedirectory` | Home directory. | no
`shell` \| `loginshell` | Login shell. | no
`sshpubkey` \| `ipasshpubkey` | List of SSH public keys. | no
`certificate` \| `usercertificate` | List of Base-64 encoded user certificates. This variable can also be used with `action: member`. | no
`fallback_to_ldap` | Allow falling back to AD DC LDAP when resolving AD trusted objects. For two-way trusts only. | no
`delete_continue` \| `continue` | Continuous mode. Don't stop on errors. Valid only if `state` is `absent`. | no
`nomembers` \| `no_members` | Suppress processing of membership attributes. Valid only if `state` is `absent`. | no
`action` | Work on idoverrideuser or member level. It can be on of `member` or `idoverrideuser` and defaults to `idoverrideuser`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-idp.md 0000664 0000000 0000000 00000012527 14600563364 0017444 0 ustar 00root root 0000000 0000000 Idp module
============
Description
-----------
The idp module allows to ensure presence and absence of idps.
Features
--------
* Idp management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaidp module.
Requirements
------------
**Controller**
* Ansible version: 2.13
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure keycloak idp my-keycloak-idp is present:
```yaml
---
- name: Playbook to manage IPA idp.
hosts: ipaserver
become: false
tasks:
- name: Ensure keycloak idp my-keycloak-idp is present
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-keycloak-idp
provider: keycloak
organization: main
base_url: keycloak.idm.example.com:8443/auth
client_id: my-client-id
```
Example playbook to make sure keycloak idp my-keycloak-idp is absent:
```yaml
---
- name: Playbook to manage IPA idp.
hosts: ipaserver
become: false
tasks:
- name: Ensure keycloak idp my-keycloak-idp is absent
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-keycloak-idp
delete_continue: true
state: absent
```
Example playbook to make sure github idp my-github-idp is present:
```yaml
---
- name: Playbook to manage IPA idp.
hosts: ipaserver
become: false
tasks:
- name: Ensure github idp my-github-idp is present
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-github-idp
provider: github
client_id: my-github-client-id
```
Example playbook to make sure google idp my-google-idp is present using provider defaults without specifying provider:
```yaml
---
- name: Playbook to manage IPA idp.
hosts: ipaserver
become: false
tasks:
- name: Ensure google idp my-google-idp is present using provider defaults without specifying provider
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-google-idp
auth_uri: https://accounts.google.com/o/oauth2/auth
dev_auth_uri: https://oauth2.googleapis.com/device/code
token_uri: https://oauth2.googleapis.com/token
keys_uri: https://www.googleapis.com/oauth2/v3/certs
userinfo_uri: https://openidconnect.googleapis.com/v1/userinfo
client_id: my-google-client-id
scope: "openid email"
idp_user_id: email
```
Example playbook to make sure google idp my-google-idp is present using provider:
```yaml
---
- name: Playbook to manage IPA idp.
hosts: ipaserver
become: false
tasks:
- name: Ensure google idp my-google-idp is present using provider
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-google-idp
provider: google
client_id: my-google-client-id
```
Example playbook to make sure idps my-keycloak-idp, my-github-idp and my-google-idp are absent:
```yaml
---
- name: Playbook to manage IPA idp.
hosts: ipaserver
become: false
tasks:
- name: Ensure idps my-keycloak-idp, my-github-idp and my-google-idp are absent
ipaidp:
ipaadmin_password: SomeADMINpassword
name:
- my-keycloak-idp
- my-github-idp
- my-google-idp
delete_continue: true
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to true. (bool) | false
`name` \| `cn` | The list of idp name strings. | yes
auth_uri \| ipaidpauthendpoint | OAuth 2.0 authorization endpoint string. | no
dev_auth_uri \| ipaidpdevauthendpoint | Device authorization endpoint string. | no
token_uri \| ipaidptokenendpoint | Token endpoint string. | no
userinfo_uri \| ipaidpuserinfoendpoint | User information endpoint string. | no
keys_uri \| ipaidpkeysendpoint | JWKS endpoint string. | no
issuer_url \| ipaidpissuerurl | The Identity Provider OIDC URL string. | no
client_id \| ipaidpclientid | OAuth 2.0 client identifier string. | no
secret \| ipaidpclientsecret | OAuth 2.0 client secret string. | no
scope \| ipaidpscope | OAuth 2.0 scope string. Multiple scopes separated by space. | no
idp_user_id \| ipaidpsub | Attribute string for user identity in OAuth 2.0 userinfo. | no
provider \| ipaidpprovider | Pre-defined template string. This provides the provider defaults, which can be overridden with the other IdP options. Choices: ["google","github","microsoft","okta","keycloak"] | no
organization \| ipaidporg | Organization ID string or Realm name for IdP provider templates. | no
base_url \| ipaidpbaseurl | Base URL string for IdP provider templates. | no
rename \| new_name | New name for the Identity Provider server object. Only with `state: renamed`. | no
delete_continue \| continue | Continuous mode. Don't stop on errors. Valid only if `state` is `absent`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, `renamed`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-idrange.md 0000664 0000000 0000000 00000014245 14600563364 0020300 0 ustar 00root root 0000000 0000000 Idrange module
============
Description
-----------
The idrange module allows the management of ID ranges.
In general it is not necessary to modify or delete ID ranges. If there is no other way to achieve a certain configuration than to modify or delete an ID range it should be done with great care. Because UIDs are stored in the file system and are used for access control it might be possible that users are allowed to access files of other users if an ID range got deleted and reused for a different domain.
Use cases
---------
* Add an ID range from a transitively trusted domain
If the trusted domain (A) trusts another domain (B) as well and this trust is transitive 'ipa trust-add domain-A' will only create a range for domain A. The ID range for domain B must be added manually.
* Add an additional ID range for the local domain
If the ID range of the local domain is exhausted, i.e. no new IDs can be assigned to Posix users or groups by the DNA plugin, a new range has to be created to allow new users and groups to be added. (Currently there is no connection between this range CLI and the DNA plugin, but a future version might be able to modify the configuration of the DNS plugin as well).
Features
--------
* ID Range management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaidrange module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to ensure a local domain idrange is present:
```yaml
---
- name: Playbook to manage IPA idrange.
hosts: ipaserver
become: no
tasks:
- name: Ensure an ID Range for the local domain is present.
ipaidrange:
ipaadmin_password: SomeADMINpassword
name: local_domain_id_range
base_id: 150000
range_size: 200000
```
Example playbook to ensure a local domain idrange is present, with RID and secondary RID base values:
```yaml
---
- name: Playbook to manage IPA idrange.
hosts: ipaserver
become: no
tasks:
- name: Ensure local idrange is present
ipaidrange:
ipaadmin_password: SomeADMINpassword
name: local_domain_id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
secondary_rid_base: 200000000
```
Example playbook to ensure an AD-trust idrange is present, with range type 'trust-ad' and using domain SID:
```yaml
---
- name: Playbook to manage IPA idrange.
hosts: ipaserver
become: no
tasks:
- name: Ensure AD-trust idrange is present
ipaidrange:
ipaadmin_password: SomeADMINpassword
name: ad_id_range
base_id: 150000000
range_size: 200000
idrange_type: ipa-ad-trust
dom_sid: S-1-5-21-2870384104-3340008087-3140804251
```
Example playbook to ensure an AD-trust idrange is present, with range type 'trust-ad-posix' and using domain SID:
```yaml
---
- name: Playbook to manage IPA idrange.
hosts: ipaserver
become: no
tasks:
- name: Ensure AD-trust idrange is present
ipaidrange:
name: ad_posix_id_range
base_id: 150000000
range_size: 200000
idrange_type: ipa-ad-trust-posix
dom_name: ad.ipa.test
```
Example playbook to ensure an AD-trust idrange has auto creation of groups set to 'hybrid':
```yaml
---
- name: Playbook to manage IPA idrange.
hosts: ipaserver
become: no
tasks:
- name: Modify AD-trust idrange 'auto_private_groups'
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
auto_private_groups: "hybrid"
```
Example playbook to make sure an idrange is absent:
```yaml
---
- name: Playbook to manage IPA idrange.
hosts: ipaserver
become: no
tasks:
- name: Ensure ID range 'ad_id_range' is absent.
ipaidrange:
ipaadmin_password: SomeADMINpassword
name: ad_id_range
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of idrange name strings. | yes
`base_id` \| `ipabaseid` | First Posix ID of the range. (int) | yes, if `state: present`
`range_size` \| `ipaidrangesize` | Number of IDs in the range. (int) | yes, if `state: present`
`rid_base` \| `ipabaserid` | First RID of the corresponding RID range. (int) | no
`secondary_rid_base` \| `ipasecondarybaserid` | First RID of the secondary RID range. (int) | no
`dom_sid` \| `ipanttrusteddomainsid` | Domain SID of the trusted domain. | no
`idrange_type` \| `iparangetype` | ID range type, one of `ipa-ad-trust`, `ipa-ad-trust-posix`, `ipa-local`. Only valid if idrange does not exist. | no
`dom_name` \| `ipanttrusteddomainname` | Name of the trusted domain. Can only be used when `ipaapi_context: server`. | no
`auto_private_groups` \| `ipaautoprivategroups` | Auto creation of private groups, one of `true`, `false`, `hybrid`. | no
`delete_continue` \| `continue` | Continuous mode: don't stop on errors. Valid only if `state` is `absent`. Default: `no` (bool) | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Notes
=====
DNA plugin in 389-ds will allocate IDs based on the ranges configured for the local domain. Currently the DNA plugin *cannot* be reconfigured itself based on the local ranges set via this family of commands.
Manual configuration change has to be done in the DNA plugin configuration for the new local range. Specifically, The dnaNextRange attribute of 'cn=Posix IDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config' has to be modified to match the new range.
Authors
=======
Rafael Guterres Jeffman
ansible-freeipa-master/README-idview.md 0000664 0000000 0000000 00000010244 14600563364 0020151 0 ustar 00root root 0000000 0000000 Idview module
============
Description
-----------
The idview module allows to ensure presence and absence of idviews and idview host members.
Use Cases
---------
With ID views it is possible to override user or group attributes for users stored in the LDAP server. For example the login name, home directory, certificate for authentication or SSH keys. An ID view is client-side and specifies new values for user or group attributes and also the client host or hosts on which the values apply.
The ID view and the applied hosts are managed with idview, the user attributes are managed with idoverrideuser and the group attributes with idoverridegroup.
Features
--------
* Idview management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaidview module.
Requirements
------------
**Controller**
* Ansible version: 2.13
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure idview "test_idview" is present:
```yaml
---
- name: Playbook to manage IPA idview.
hosts: ipaserver
become: false
tasks:
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
```
Example playbook to make sure idview "test_idview" member host "testhost.example.com" is present:
```yaml
---
- name: Playbook to manage IPA idview host member.
hosts: ipaserver
become: false
tasks:
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
host: testhost.example.com
action: member
```
Example playbook to make sure idview "test_idview" member host "testhost.example.com" is absent:
```yaml
---
- name: Playbook to manage IPA idview host member.
hosts: ipaserver
become: false
tasks:
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
host: testhost.example.com
action: member
state: absent
```
Example playbook to make sure idview "test_idview" is present with domain_resolution_order for "ad.example.com:ipa.example.com":
```yaml
---
- name: Playbook to manage IPA idview host member.
hosts: ipaserver
become: false
tasks:
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
domain_resolution_order: "ad.example.com:ipa.example.com"
```
Example playbook to make sure idview "test_idview" is absent:
```yaml
---
- name: Playbook to manage IPA idview.
hosts: ipaserver
become: false
tasks:
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to true. (bool) | no
`name` \| `cn` | The list of idview name strings. | yes
`description` \| `desc` | The description string of the idview. | no
`domain_resolution_order` \| `ipadomainresolutionorder` | Colon-separated list of domains used for short name qualification. | no
`host` \| `hosts` | List of hosts to apply the ID View to. A host can only be applied to a single idview at any time. Applying a host that is already applied to a different idview will change the idview the host is applied to to the new one. | no
`rename` \| `new_name` | Rename the ID view object to the new name string. Only usable with `state: renamed`. | no
`delete_continue` \| `continue` | Continuous mode. Don't stop on errors. Valid only if `state` is `absent`. | no
`action` | Work on idview or member level. It can be on of `member` or `idview` and defaults to `idview`. | no
`state` | The state to ensure. It can be one of `present`, `absent` and `renamed`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-location.md 0000664 0000000 0000000 00000003613 14600563364 0020474 0 ustar 00root root 0000000 0000000 Location module
===============
Description
-----------
The location module allows to ensure presence and absence of locations.
Features
--------
* Location management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipalocation module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure location "my_location1" is present:
```yaml
---
- name: Playbook to manage IPA location.
hosts: ipaserver
become: yes
tasks:
- ipalocation:
ipaadmin_password: SomeADMINpassword
name: my_location1
description: My Location 1
```
Example playbook to make sure location "my_location1" is absent:
```yaml
---
- name: Playbook to manage IPA location.
hosts: ipaserver
become: yes
tasks:
- ipalocation:
ipaadmin_password: SomeADMINpassword
name: my_location1
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `idnsname` | The list of location name strings. | yes
`description` | The IPA location string | false
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-netgroup.md 0000664 0000000 0000000 00000007761 14600563364 0020537 0 ustar 00root root 0000000 0000000 Netgroup module
============
Description
-----------
The netgroup module allows to ensure presence and absence of netgroups.
Features
--------
* Netgroup management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipanetgroup module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure netgroup "my_netgroup1" is present:
```yaml
---
- name: Playbook to manage IPA netgroup.
hosts: ipaserver
become: no
tasks:
- name: Ensure netgroup my_netgroup1 is present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: my_netgroup1
description: My netgroup 1
```
Example playbook to make sure netgroup "my_netgroup1" is absent:
```yaml
---
- name: Playbook to manage IPA netgroup.
hosts: ipaserver
become: no
tasks:
- name: Ensure netgroup my_netgroup1 is absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: my_netgroup1
state: absent
```
Example playbook to make sure netgroup is present with user "user1"
```yaml
---
- name: Playbook to manage IPA netgroup.
hosts: ipaserver
become: no
tasks:
- name: Ensure netgroup is present with user "user1"
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: TestNetgroup1
user: user1
action: member
```
Example playbook to make sure netgroup user, "user1", is absent
```yaml
---
- name: Playbook to manage IPA netgroup.
hosts: ipaserver
become: no
tasks:
- name: Ensure netgroup user, "user1", is absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: TestNetgroup1
user: "user1"
action: member
state: absent
```
Example playbook to make sure netgroup is present with members
```yaml
---
- name: Playbook to manage IPA netgroup.
hosts: ipaserver
become: no
tasks:
- name: Ensure netgroup members are present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: TestNetgroup1
user: user1,user2
group: group1
host: host1
hostgroup: ipaservers
netgroup: admins
action: member
```
Example playbook to make sure 2 netgroups TestNetgroup1, admins are absent
```yaml
---
- name: Playbook to manage IPA netgroup.
hosts: ipaserver
become: no
tasks:
- name: Ensure netgroups are absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name:
- TestNetgroup1
- admins
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of netgroup name strings. | yes
`description` | Netgroup description | no
`nisdomain` | NIS domain name | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`user` | List of user name strings assigned to this netgroup. | no
`group` | List of group name strings assigned to this netgroup. | no
`host` | List of host name strings assigned to this netgroup. | no
`hostgroup` | List of hostgroup name strings assigned to this netgroup. | no
`netgroup` | List of netgroup name strings assigned to this netgroup. | no
`action` | Work on group or member level. It can be on of `member` or `netgroup` and defaults to `netgroup`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Denis Karpelevich
ansible-freeipa-master/README-permission.md 0000664 0000000 0000000 00000012260 14600563364 0021052 0 ustar 00root root 0000000 0000000 Permission module
============
Description
-----------
The permission module allows to ensure presence and absence of permissions and permission members.
Features
--------
* Permission management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipapermission module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure permission "MyPermission" is present:
```yaml
---
- name: Playbook to handle IPA permissions
hosts: ipaserver
become: yes
tasks:
- name: Ensure permission MyPermission is present
ipapermission:
ipaadmin_password: SomeADMINpassword
name: MyPermission
object_type: host
right: all
```
Example playbook to ensure permission "MyPermission" is present with attr carlicense:
```yaml
---
- name: Playbook to handle IPA permissions
hosts: ipaserver
become: yes
tasks:
- name: Ensure permission "MyPermission" is present with attr carlicense
ipapermission:
ipaadmin_password: SomeADMINpassword
name: MyPermission
object_type: host
right: all
attrs:
- carlicense
```
Example playbook to ensure attr gecos is present in permission "MyPermission":
```yaml
---
- name: Playbook to handle IPA permissions
hosts: ipaserver
become: yes
tasks:
- name: Ensure attr gecos is present in permission "MyPermission"
ipapermission:
ipaadmin_password: SomeADMINpassword
name: MyPermission
attrs:
- gecos
action: member
```
Example playbook to ensure attr gecos is absent in permission "MyPermission":
```yaml
---
- name: Playbook to handle IPA permissions
hosts: ipaserver
become: yes
tasks:
- name: Ensure attr gecos is present in permission "MyPermission"
ipapermission:
ipaadmin_password: SomeADMINpassword
name: MyPermission
attrs:
- gecos
action: member
state: absent
```
Example playbook to make sure permission "MyPermission" is absent:
```yaml
---
- name: Playbook to handle IPA permissions
hosts: ipaserver
become: yes
tasks:
- name: Ensure permission "MyPermission" is absent
ipapermission:
ipaadmin_password: SomeADMINpassword
name: MyPermission
state: absent
```
Example playbook to make sure permission "MyPermission" is renamed to "MyNewPermission":
```yaml
---
- name: Playbook to handle IPA permissions
hosts: ipaserver
become: yes
tasks:
- name: Ensure permission "MyPermission" is renamed to "MyNewPermission
ipapermission:
ipaadmin_password: SomeADMINpassword
name: MyPermission
rename: MyNewPermission
state: renamed
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The permission name string. | yes
`right` \| `ipapermright` | Rights to grant. It can be a list of one or more of `read`, `search`, `compare`, `write`, `add`, `delete`, and `all` default: `all` | no
`attrs` | All attributes to which the permission applies. | no
`bindtype` \| `ipapermbindruletype` | Bind rule type. It can be one of `permission`, `all`, `self`, or `anonymous` defaults to `permission` for new permissions. Bind rule type `self` can only be used on IPA versions 4.8.7 or up.| no
`subtree` \| `ipapermlocation` | Subtree to apply permissions to | no
`filter` \| `extratargetfilter` | Extra target filter | no
`rawfilter` \| `ipapermtargetfilter` | All target filters | no
`target` \| `ipapermtarget` | Optional DN to apply the permission to | no
`targetto` \| `ipapermtargetto` | Optional DN subtree where an entry can be moved to | no
`targetfrom` \| `ipapermtargetfrom` | Optional DN subtree from where an entry can be moved | no
`memberof` | Target members of a group (sets memberOf targetfilter) | no
`targetgroup` | User group to apply permissions to (sets target) | no
`object_type` | Type of IPA object (sets subtree and objectClass targetfilter) | no
`no_members` | Suppress processing of membership | no
`rename` \| `new_name` | Rename the permission object | no
`action` | Work on permission or member level. It can be on of `member` or `permission` and defaults to `permission`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, or `renamed` default: `present`. | no
The `includedattrs` and `excludedattrs` variables are only usable for managed permisions and are not exposed by the module. Using `attrs` for managed permissions will result in the automatic generation of `includedattrs` and `excludedattrs` in the IPA server.
Authors
=======
Seth Kress
ansible-freeipa-master/README-privilege.md 0000664 0000000 0000000 00000006631 14600563364 0020655 0 ustar 00root root 0000000 0000000 Privilege module
================
Description
-----------
The privilege module allows to ensure presence and absence of privileges and privilege members.
Features
--------
* Privilege management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaprivilege module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure privilege "Broad Privilege" is present:
```yaml
---
- name: Playbook to manage IPA privilege.
hosts: ipaserver
become: yes
tasks:
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
description: Broad Privilege
```
Example playbook to make sure privilege "Broad Privilege" member permission has multiple values:
```yaml
---
- name: Playbook to manage IPA privilege permission member.
hosts: ipaserver
become: yes
tasks:
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
permission:
- "Write IPA Configuration"
- "System: Write DNS Configuration"
- "System: Update DNS Entries"
action: member
```
Example playbook to make sure privilege "Broad Privilege" member permission 'Write IPA Configuration' is absent:
```yaml
---
- name: Playbook to manage IPA privilege permission member.
hosts: ipaserver
become: yes
tasks:
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
permission:
- "Write IPA Configuration"
action: member
state: absent
```
Example playbook to rename privilege "Broad Privilege" to "DNS Special Privilege":
```yaml
---
- name: Playbook to manage IPA privilege.
hosts: ipaserver
become: yes
tasks:
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
rename: DNS Special Privilege
state: renamed
```
Example playbook to make sure privilege "DNS Special Privilege" is absent:
```yaml
---
- name: Playbook to manage IPA privilege.
hosts: ipaserver
become: yes
- name: Ensure privilege Broad Privilege is absent
ipaadmin_password: SomeADMINpassword
name: DNS Special Privilege
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin`. | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node. | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of privilege name strings. | yes
`description` | Privilege description. | no
`rename` \| `new_name` | Rename the privilege object. | no
`permission` | Permissions to be added to the privilege. | no
`action` | Work on privilege or member level. It can be one of `member` or `privilege` and defaults to `privilege`. | no
`state` | The state to ensure. It can be one of `present`, `absent` or `renamed`, default: `present`. | no
Authors
=======
Rafael Guterres Jeffman
ansible-freeipa-master/README-pwpolicy.md 0000664 0000000 0000000 00000010521 14600563364 0020526 0 ustar 00root root 0000000 0000000 Pwpolicy module
===============
Description
-----------
The pwpolicy module allows to ensure presence and absence of pwpolicies.
Features
--------
* Pwpolicy management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipapwpolicy module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to ensure presence of pwpolicies for exisiting group ops:
```yaml
tasks:
- name: Ensure presence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
name: ops
minlife: 7
maxlife: 49
history: 5
priority: 1
lockouttime: 300
minlength: 8
maxfail: 3
```
Example playbook to ensure absence of pwpolicies for group ops:
```yaml
---
- name: Playbook to handle pwpolicies
hosts: ipaserver
become: true
tasks:
# Ensure absence of pwpolicies for group ops
- ipapwpolicy:
ipaadmin_password: SomeADMINpassword
name: ops
state: absent
```
Example playbook to ensure maxlife is set to 49 in global policy:
```yaml
---
- name: Playbook to handle pwpolicies
hosts: ipaserver
become: true
tasks:
# Ensure maxlife is set to 49 in global policy
- ipapwpolicy:
ipaadmin_password: SomeADMINpassword
maxlife: 49
```
Example playbook to ensure password grace period is set to 3 in global policy:
```yaml
---
- name: Playbook to handle pwpolicies
hosts: ipaserver
become: true
tasks:
# Ensure maxlife is set to 49 in global policy
- ipapwpolicy:
ipaadmin_password: SomeADMINpassword
gracelimit: 3
```
Example playbook to ensure password grace period is set to unlimited in global policy:
```yaml
---
- name: Playbook to handle pwpolicies
hosts: ipaserver
become: true
tasks:
# Ensure maxlife is set to 49 in global policy
- ipapwpolicy:
ipaadmin_password: SomeADMINpassword
gracelimit: -1
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of pwpolicy name strings. If name is not given, `global_policy` will be used automatically. | no
`maxlife` \| `krbmaxpwdlife` | Maximum password lifetime in days. (int or "") | no
`minlife` \| `krbminpwdlife` | Minimum password lifetime in hours. (int or "") | no
`history` \| `krbpwdhistorylength` | Password history size. (int or "") | no
`minclasses` \| `krbpwdmindiffchars` | Minimum number of character classes. (int or "") | no
`minlength` \| `krbpwdminlength` | Minimum length of password. (int or "") | no
`priority` \| `cospriority` | Priority of the policy, higher number means lower priority. (int or "") | no
`maxfail` \| `krbpwdmaxfailure` | Consecutive failures before lockout. (int or "") | no
`failinterval` \| `krbpwdfailurecountinterval` | Period after which failure count will be reset in seconds. (int or "") | no
`lockouttime` \| `krbpwdlockoutduration` | Period for which lockout is enforced in seconds. (int or "") | no
`maxrepeat` \| `ipapwdmaxrepeat` | Maximum number of same consecutive characters. Requires IPA 4.9+ (int or "") | no
`maxsequence` \| `ipapwdmaxsequence` | The maximum length of monotonic character sequences (abcd). Requires IPA 4.9+ (int or "") | no
`dictcheck` \| `ipapwdictcheck` | Check if the password is a dictionary word. Requires IPA 4.9+. (bool or "") | no
`usercheck` \| `ipapwdusercheck` | Check if the password contains the username. Requires IPA 4.9+. (bool or "") | no
`gracelimit` \| `passwordgracelimit` | Number of LDAP authentications allowed after expiration. Requires IPA 4.9.10 (int or "") | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | yes
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-role.md 0000664 0000000 0000000 00000012572 14600563364 0017631 0 ustar 00root root 0000000 0000000 Role module
===========
Description
-----------
The role module allows to ensure presence, absence of roles and members of roles.
The role module is as compatible as possible to the Ansible upstream `ipa_role` module, but additionally offers role member management.
Features
--------
* Role management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the iparole module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure role is present with all members:
```yaml
---
- name: Playbook to manage IPA role with members.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
user:
- pinky
group:
- group01
host:
- host01.example.com
hostgroup:
- hostgroup01
privilege:
- Group Administrators
- User Administrators
service:
- service01
```
Example playbook to rename a role:
```yaml
- iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
rename: anotherrole
```
Example playbook to make sure role is absent:
```yaml
---
- name: Playbook to manage IPA role.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
state: absent
```
Example playbook to ensure a user is a member of a role:
```yaml
---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
user:
- pinky
action: member
```
Example playbook to ensure a group is a member of a role:
```yaml
---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
host:
- host01.example.com
action: member
```
Example playbook to ensure a host is a member of a role:
```yaml
---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
host:
- host01.example.com
action: member
```
Example playbook to ensure a hostgroup is a member of a role:
```yaml
---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
hostgroup:
- hostgroup01
action: member
```
Example playbook to ensure a service is a member of a role:
```yaml
---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
service:
- service01
action: member
```
Example playbook to ensure a privilege is a member of a role:
```yaml
---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
privilege:
- Group Administrators
- User Administrators
action: member
```
Example playbook to ensure that different members are not associated with a role.
```yaml
---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
user:
- pinky
group:
- group01
host:
- host01.example.com
hostgroup:
- hostgroup01
privilege:
- Group Administrators
- User Administrators
service:
- service01
action: member
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of role name strings. | yes
`description` | A description for the role. | no
`rename` \| `new_name` | Rename the role object. | no
`privilege` | Privileges associated to this role. | no
`user` | List of users to be assigned or not assigned to the role. | no
`group` | List of groups to be assigned or not assigned to the role. | no
`host` | List of hosts to be assigned or not assigned to the role. | no
`hostgroup` | List of hostgroups to be assigned or not assigned to the role. | no
`service` | List of services to be assigned or not assigned to the role. | no
`action` | Work on role or member level. It can be on of `member` or `role` and defaults to `role`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Rafael Jeffman
ansible-freeipa-master/README-selfservice.md 0000664 0000000 0000000 00000006737 14600563364 0021210 0 ustar 00root root 0000000 0000000 Selfservice module
=================
Description
-----------
The selfservice module allows to ensure presence, absence of selfservices and selfservice attributes.
Features
--------
* Selfservice management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaselfservice module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure selfservice "Users can manage their own name details" is present:
```yaml
---
- name: Playbook to manage IPA selfservice.
hosts: ipaserver
become: yes
tasks:
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
permission: read
attribute:
- title
- initials
```
Example playbook to make sure selfservice "Users can manage their own name details" is absent:
```yaml
---
- name: Playbook to manage IPA selfservice.
hosts: ipaserver
become: yes
tasks:
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
state: absent
```
Example playbook to make sure "Users can manage their own name details" member attribute initials is present:
```yaml
---
- name: Playbook to manage IPA selfservice.
hosts: ipaserver
become: yes
tasks:
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
attribute:
- initials
action: member
```
Example playbook to make sure "Users can manage their own name details" member attribute initials is absent:
```yaml
---
- name: Playbook to manage IPA selfservice.
hosts: ipaserver
become: yes
tasks:
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
attribute:
- initials
action: member
state: absent
```
Example playbook to make sure selfservice "Users can manage their own name details" is absent:
```yaml
---
- name: Playbook to manage IPA selfservice.
hosts: ipaserver
become: yes
tasks:
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `aciname` | The list of selfservice name strings. | yes
`permission` \| `permissions` | The permission to grant `read`, `read,write`, `write`]. Default is `write`. | no
`attribute` \| `attrs` | The attribute list to which the selfservice applies. | no
`action` | Work on selfservice or member level. It can be on of `member` or `selfservice` and defaults to `selfservice`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-server.md 0000664 0000000 0000000 00000014452 14600563364 0020175 0 ustar 00root root 0000000 0000000 Server module
============
Description
-----------
The server module allows to ensure presence and absence of servers. The module requires an existing server, the deployment of a new server can not be done with the module.
Features
--------
* Server management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaserver module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure server "server.example.com" is already present in the topology:
```yaml
---
- name: Playbook to manage IPA server.
hosts: ipaserver
become: yes
tasks:
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
```
This task is not deploying a new server, it is only checking if the server eists. It will therefore fail if the server does not exist.
Example playbook to make sure server "server.example.com" has location mylocation:
```yaml
---
- name: Playbook to manage IPA server.
hosts: ipaserver
become: yes
tasks:
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
location: mylocation
```
Example playbook to make sure server "server.example.com" does not have a location:
```yaml
---
- name: Playbook to manage IPA server.
hosts: ipaserver
become: yes
tasks:
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
location: ""
```
Example playbook to make sure server "server.example.com" has service weight 1:
```yaml
---
- name: Playbook to manage IPA server.
hosts: ipaserver
become: yes
tasks:
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
service_weight: 1
```
Example playbook to make sure server "server.example.com" does not have a service weight:
```yaml
---
- name: Playbook to manage IPA server.
hosts: ipaserver
become: yes
tasks:
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
service_weight: -1
```
Example playbook to make sure server "server.example.com" is hidden:
```yaml
---
- name: Playbook to manage IPA server.
hosts: ipaserver
become: yes
tasks:
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
hidden: yes
```
Example playbook to make sure server "server.example.com" is not hidden:
```yaml
---
- name: Playbook to manage IPA server.
hosts: ipaserver
become: yes
tasks:
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
hidden: no
```
Example playbook to make sure server "server.example.com" is absent from the topology:
```yaml
---
- name: Playbook to manage IPA server.
hosts: ipaserver
become: yes
tasks:
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
state: absent
```
Example playbook to make sure server "server.example.com" is absent from the topology in continuous mode to ignore errors:
```yaml
---
- name: Playbook to manage IPA server.
hosts: ipaserver
become: yes
tasks:
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
continue: yes
state: absent
```
Example playbook to make sure server "server.example.com" is absent from the topology with skipping the last of role check:
```yaml
---
- name: Playbook to manage IPA server.
hosts: ipaserver
become: yes
tasks:
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
ignore_last_of_role: yes
state: absent
```
Example playbook to make sure server "server.example.com" is absent from the topology with skipping the topology disconnect check:
```yaml
---
- name: Playbook to manage IPA server.
hosts: ipaserver
become: yes
tasks:
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
ignore_topology_disconnect: yes
state: absent
```
Example playbook to make sure server "server.example.com" is absent from the domain in force mode even if it does not exist:
```yaml
---
- name: Playbook to manage IPA server.
hosts: ipaserver
become: yes
tasks:
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
force: yes
state: absent
```
This task will always report a change.
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of server name strings. | yes
`location` \| `ipalocation_location` | The server DNS location. Only available with 'state: present'. Use "" for location reset. | no
`service_weight` \| `ipaserviceweight` | Weight for server services. Type Values 0 to 65535, -1 for weight reset. Only available with 'state: present'. (int) | no
`hidden` | Set hidden state of a server. Only available with 'state: present'. (bool) | no
`no_members` | Suppress processing of membership attributes. Only avialable with 'state: present'. (bool) | no
`delete_continue` \| `continue` | Continuous mode: Don't stop on errors. Only available with 'state: absent'. (bool) | no
`ignore_last_of_role` | Skip a check whether the last CA master or DNS server is removed. Only available with 'state: absent'. (bool) | no
`ignore_topology_disconnect` | Ignore topology connectivity problems after removal. Only available with 'state: absent'. (bool) | no
`force` | Force server removal even if it does not exist. Will always result in changed. Only available with 'state: absent'. (bool) | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. `present` is only working with existing servers. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-service.md 0000664 0000000 0000000 00000025601 14600563364 0020325 0 ustar 00root root 0000000 0000000 Service module
==============
Description
-----------
The service module allows to ensure presence and absence of services.
Features
--------
* Service management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaservice module.
Some variables are only supported on newer versions of FreeIPA. Check `Variables` section for details.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FReeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure service is present:
```yaml
---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure service is present
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
certificate: |
- MIIC/zCCAeegAwIBAgIUMNHIbn+hhrOVew/2WbkteisV29QwDQYJKoZIhvcNAQELBQAw
DzENMAsGA1UEAwwEdGVzdDAeFw0yMDAyMDQxNDQxMDhaFw0zMDAyMDExNDQxMDhaMA8xDT
ALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+XVVGFYpH
VkcDfVnNInE1Y/pFciegdzqTjMwUWlRL4Zt3u96GhaMLRbtk+OfEkzLUAhWBOwEraELJzM
LJOMvjYF3C+TiGO7dStFLikZmccuSsSIXjnzIPwBXa8KvgRVRyGLoVvGbLJvmjfMXp0nIT
oTx/i74KF9S++WEes9H5ErJ99CDhLKFgq0amnvsgparYXhypHaRLnikn0vQINt55YoEd1s
4KrvEcD2VdZkIMPbLRu2zFvMprF3cjQQG4LT9ggfEXNIPZ1nQWAnAsu7OJEkNF+E4Mkmpc
xj9aGUVt5bsq1D+Tzj3GsidSX0nSNcZ2JltXRnL/5v63g5cZyE+nAgMBAAGjUzBRMB0GA1
UdDgQWBBRV0j7JYukuH/r/t9+QeNlRLXDlEDAfBgNVHSMEGDAWgBRV0j7JYukuH/r/t9+Q
eNlRLXDlEDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCgVy1+1kNwHs
5y1Zp0WjMWGCJC6/zw7FDG4OW5r2GJiCXZYdJ0UonY9ZtoVLJPrp2/DAv1m5DtnDhBYqic
uPgLzEkOS1KdTi20Otm/J4yxLLrZC5W4x0XOeSVPXOJuQWfwQ5pPvKkn6WxYUYkGwIt1OH
2nSMngkbami3CbSmKZOCpgQIiSlQeDJ8oGjWFMLDymYSHoVOIXHwNoooyEiaio3693l6no
obyGv49zyCVLVR1DC7i6RJ186ql0av+D4vPoiF5mX7+sKC2E8xEj9uKQ5GTWRh59VnRBVC
/SiMJ/H78tJnBAvoBwXxSEvj8Z3Kjm/BQqZfv4IBsA5yqV7MVq
pac_type: PAD
auth_ind: otp
requires_pre_auth: false
ok_as_delegate: false
ok_to_auth_as_delegate: false
skip_host_check: true
force: true
```
Example playbook to make sure service is absent:
```yaml
---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure service is present
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
state: absent
```
Example playbook to make sure service is disabled:
```yaml
---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure service is present
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
state: disabled
```
Example playbook to add a service even if the host object does not exist, but only if it does have a DNS entry:
```yaml
---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure service is present
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
skip_host_check: true
force: false
```
Example playbook to add a service if it does have a DNS entry, but host object exits:
```yaml
---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure service is present
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
skip_host_check: false
force: true
```
Example playbook to ensure service has a certificate:
```yaml
---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure service member certificate is present.
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
certificate: |
- MIIC/zCCAeegAwIBAgIUMNHIbn+hhrOVew/2WbkteisV29QwDQYJKoZIhvcNAQELBQAw
DzENMAsGA1UEAwwEdGVzdDAeFw0yMDAyMDQxNDQxMDhaFw0zMDAyMDExNDQxMDhaMA8xDT
ALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+XVVGFYpH
VkcDfVnNInE1Y/pFciegdzqTjMwUWlRL4Zt3u96GhaMLRbtk+OfEkzLUAhWBOwEraELJzM
LJOMvjYF3C+TiGO7dStFLikZmccuSsSIXjnzIPwBXa8KvgRVRyGLoVvGbLJvmjfMXp0nIT
oTx/i74KF9S++WEes9H5ErJ99CDhLKFgq0amnvsgparYXhypHaRLnikn0vQINt55YoEd1s
4KrvEcD2VdZkIMPbLRu2zFvMprF3cjQQG4LT9ggfEXNIPZ1nQWAnAsu7OJEkNF+E4Mkmpc
xj9aGUVt5bsq1D+Tzj3GsidSX0nSNcZ2JltXRnL/5v63g5cZyE+nAgMBAAGjUzBRMB0GA1
UdDgQWBBRV0j7JYukuH/r/t9+QeNlRLXDlEDAfBgNVHSMEGDAWgBRV0j7JYukuH/r/t9+Q
eNlRLXDlEDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCgVy1+1kNwHs
5y1Zp0WjMWGCJC6/zw7FDG4OW5r2GJiCXZYdJ0UonY9ZtoVLJPrp2/DAv1m5DtnDhBYqic
uPgLzEkOS1KdTi20Otm/J4yxLLrZC5W4x0XOeSVPXOJuQWfwQ5pPvKkn6WxYUYkGwIt1OH
2nSMngkbami3CbSmKZOCpgQIiSlQeDJ8oGjWFMLDymYSHoVOIXHwNoooyEiaio3693l6no
obyGv49zyCVLVR1DC7i6RJ186ql0av+D4vPoiF5mX7+sKC2E8xEj9uKQ5GTWRh59VnRBVC
/SiMJ/H78tJnBAvoBwXxSEvj8Z3Kjm/BQqZfv4IBsA5yqV7MVq
action: member
state: present
```
Example playbook to add a principal to the service:
```yaml
---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Principal host/principal.example.com present in service.
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
principal: host/principal.example.com
action: member
```
Example playbook to enable a host to manage service:
```yaml
---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure host can manage service, again.
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
host: host1.example.com
action: member
```
Example playbook to allow users, groups, hosts or hostgroups to create a keytab of this service:
```yaml
---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Allow users, groups, hosts or host groups to create a keytab of this service.
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- host1.example.com
- host2.example.com
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
```
Example playbook to allow users, groups, hosts or hostgroups to retrieve a keytab of this service:
```yaml
---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Allow users, groups, hosts or host groups to retrieve a keytab of this service.
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `service` | The list of service name strings. | yes
`certificate` \| `usercertificate` | Base-64 encoded service certificate. | no
`pac_type` \| `ipakrbauthzdata` | Supported PAC type. It can be one of `MS-PAC`, `PAD`, or `NONE`. Use empty string to reset pac_type to the initial value. | no
`auth_ind` \| `krbprincipalauthind` | Defines an allow list for Authentication Indicators. It can be any of `otp`, `radius`, `pkinit`, `hardened`, `idp` or `""`. An additional check ensures that only types can be used that are supported by the IPA version. Use empty string to reset auth_ind to the initial value. | no
`requires_pre_auth` \| `ipakrbrequirespreauth` | Pre-authentication is required for the service. Default to true. (bool) | no
`ok_as_delegate` \| `ipakrbokasdelegate` | Client credentials may be delegated to the service. Default to false. (bool) | no
`ok_to_auth_as_delegate` \| `ipakrboktoauthasdelegate` | The service is allowed to authenticate on behalf of a client. Default to false. (bool) | no
`skip_host_check` | Force service to be created even when host object does not exist to manage it. Only usable with IPA versions 4.7.0 and up. Default to false. (bool)| no
`force` | Force principal name even if host not in DNS. Default to false. (bool) | no
`host` \| `managedby_host`| Hosts that can manage the service. | no
`principal` \| `krbprincipalname` | List of principal aliases for the service. | no
`allow_create_keytab_user` \| `ipaallowedtoperform_write_keys_user` | Users allowed to create a keytab of this host. | no
`allow_create_keytab_group` \| `ipaallowedtoperform_write_keys_group`| Groups allowed to create a keytab of this host. | no
`allow_create_keytab_host` \| `ipaallowedtoperform_write_keys_host`| Hosts allowed to create a keytab of this host. | no
`allow_create_keytab_hostgroup` \| `ipaallowedtoperform_write_keys_group`| Host groups allowed to create a keytab of this host. | no
`allow_retrieve_keytab_user` \| `ipaallowedtoperform_read_keys_user` | Users allowed to retrieve a keytab of this host. | no
`allow_retrieve_keytab_group` \| `ipaallowedtoperform_read_keys_group` | Groups allowed to retrieve a keytab of this host. | no
`allow_retrieve_keytab_host` \| `ipaallowedtoperform_read_keys_host` | Hosts allowed to retrieve a keytab from of host. | no
`allow_retrieve_keytab_hostgroup` \| `ipaallowedtoperform_read_keys_hostgroup` | Host groups allowed to retrieve a keytab of this host. | no
`continue` | Continuous mode: don't stop on errors. Valid only if `state` is `absent`. Default: `no` (bool) | no
`smb` | Service is an SMB service. If set, `cifs/` will be prefixed to the service name if needed. | no
`netbiosname` | NETBIOS name for the SMB service. Only with `smb: yes`. | no
`action` | Work on service or member level. It can be on of `member` or `service` and defaults to `service`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, or `disabled`, default: `present`. | no
Authors
=======
Rafael Jeffman
ansible-freeipa-master/README-servicedelegationrule.md 0000664 0000000 0000000 00000011303 14600563364 0023243 0 ustar 00root root 0000000 0000000 Servicedelegationrule module
============
Description
-----------
The servicedelegationrule module allows to ensure presence and absence of servicedelegationrules and servicedelegationrule members.
Features
--------
* Servicedelegationrule management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaservicedelegationrule module.
Host princpals are only usable with IPA versions 4.9.0 and up.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure servicedelegationrule delegation-rule is present:
```yaml
---
- name: Playbook to manage IPA servicedelegationrule
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationrule delegation-rule is present
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: delegation-rule
```
Example playbook to make sure servicedelegationrule delegation-rule member principal test/example.com is present:
```yaml
---
- name: Playbook to manage IPA servicedelegationrule
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationrule delegation-rule member principal test/example.com is present
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: delegation-rule
principal: test/example.com
action: member
```
Example playbook to make sure servicedelegationrule delegation-rule member principal test/example.com is absent:
```yaml
---
- name: Playbook to manage IPA servicedelegationrule
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationrule delegation-rule member principal test/example.com is absent
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: delegation-rule
principal: test/example.com
action: member
state: absent
state: absent
```
Example playbook to make sure servicedelegationrule delegation-rule member target delegation-target is present:
```yaml
---
- name: Playbook to manage IPA servicedelegationrule
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationrule delegation-rule member target delegation-target is present
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: delegation-rule
target: delegation-target
action: member
```
Example playbook to make sure servicedelegationrule delegation-rule member target delegation-target is absent:
```yaml
---
- name: Playbook to manage IPA servicedelegationrule
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationrule delegation-rule member target delegation-target is absent
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: delegation-rule
target: delegation-target
action: member
state: absent
state: absent
```
Example playbook to make sure servicedelegationrule delegation-rule is absent:
```yaml
---
- name: Playbook to manage IPA servicedelegationrule
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationrule delegation-rule is absent
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: delegation-rule
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of servicedelegationrule name strings. | yes
`principal` | The list of principals. A principal can be of the format: fqdn, fqdn@REALM, service/fqdn, service/fqdn@REALM, host/fqdn, host/fqdn@REALM, alias$, alias$@REALM, where fqdn and fqdn@REALM are host principals and the same as host/fqdn and host/fqdn@REALM. Host princpals are only usable with IPA versions 4.9.0 and up. | no
`target` \| `servicedelegationtarget` | The list of service delegation targets. | no
`action` | Work on servicedelegationrule or member level. It can be on of `member` or `servicedelegationrule` and defaults to `servicedelegationrule`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-servicedelegationtarget.md 0000664 0000000 0000000 00000007332 14600563364 0023571 0 ustar 00root root 0000000 0000000 Servicedelegationtarget module
============
Description
-----------
The servicedelegationtarget module allows to ensure presence and absence of servicedelegationtargets and servicedelegationtarget members.
Features
--------
* Servicedelegationtarget management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaservicedelegationtarget module.
Host princpals are only usable with IPA versions 4.9.0 and up.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure servicedelegationtarget delegation-target is present:
```yaml
---
- name: Playbook to manage IPA servicedelegationtarget
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationtarget delegation-target is present
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
name: delegation-target
```
Example playbook to make sure servicedelegationtarget delegation-target member principal test/example.com is present:
```yaml
---
- name: Playbook to manage IPA servicedelegationtarget
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationtarget delegation-target member principal test/example.com is present
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
name: delegation-target
principal: test/example.com
action: member
```
Example playbook to make sure servicedelegationtarget delegation-target member principal test/example.com is absent:
```yaml
---
- name: Playbook to manage IPA servicedelegationtarget
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationtarget delegation-target member principal test/example.com is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
name: delegation-target
principal: test/example.com
action: member
state: absent
state: absent
```
Example playbook to make sure servicedelegationtarget delegation-target is absent:
```yaml
---
- name: Playbook to manage IPA servicedelegationtarget
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationtarget delegation-target is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
name: delegation-target
state: absent
```
Variables
---------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of servicedelegationtarget name strings. | yes
`principal` | The list of principals. A principal can be of the format: fqdn, fqdn@REALM, service/fqdn, service/fqdn@REALM, host/fqdn, host/fqdn@REALM, alias$, alias$@REALM, where fqdn and fqdn@REALM are host principals and the same as host/fqdn and host/fqdn@REALM. Host princpals are only usable with IPA versions 4.9.0 and up. | no
`action` | Work on servicedelegationtarget or member level. It can be on of `member` or `servicedelegationtarget` and defaults to `servicedelegationtarget`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-sudocmd.md 0000664 0000000 0000000 00000004072 14600563364 0020322 0 ustar 00root root 0000000 0000000 Sudocmd module
================
Description
-----------
The sudocmd module allows to ensure presence and absence of sudo command.
The sudocmd module is as compatible as possible to the Ansible upstream `ipa_sudocmd` module.
Features
--------
* Sudo command management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipa_sudocmd module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure sudocmd exists:
```yaml
---
- name: Playbook to handle sudocmd
hosts: ipaserver
become: true
tasks:
# Ensure sudocmd is present
- ipasudocmd:
ipaadmin_password: SomeADMINpassword
name: /usr/bin/su
state: present
```
Example playbook to make sure sudocmd is absent:
```yaml
---
- name: Playbook to handle sudocmd
hosts: ipaserver
become: true
tasks:
# Ensure sudocmd are absent
- ipasudocmd:
ipaadmin_password: SomeADMINpassword
name: /usr/bin/su
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `sudocmd` | The sudo command strings. | yes
`description` | The command description string. | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | no
Authors
=======
Rafael Guterres Jeffman
ansible-freeipa-master/README-sudocmdgroup.md 0000664 0000000 0000000 00000006710 14600563364 0021400 0 ustar 00root root 0000000 0000000 Sudocmdgroup module
===================
Description
-----------
The sudocmdgroup module allows to ensure presence and absence of sudocmdgroups and members of sudocmdgroups.
The sudocmdgroup module is as compatible as possible to the Ansible upstream `ipa_sudocmdgroup` module, but additionally offers to make sure that sudocmds are present or absent in a sudocmdgroup.
Features
--------
* Sudocmdgroup management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipasudocmdgroup module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure sudocmdgroup is present:
```yaml
---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
# Ensure sudocmdgroup is present
- ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
name: group01
description: Group of important commands
```
Example playbook to make sure that a sudo command and sudocmdgroups are present in existing sudocmdgroup:
```yaml
---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
# Ensure sudo commands are present in existing sudocmdgroup
- ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
name: group01
sudocmd:
- /usr/bin/su
- /usr/bin/less
action: member
```
`action` controls if the sudocmdgroup or member will be handled. To add or remove members, set `action` to `member`.
Example playbook to make sure that a sudo command and sudocmdgroups are absent in sudocmdgroup:
```yaml
---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
# Ensure sudocmds are absent in existing sudocmdgroup
- ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
name: group01
sudocmd:
- /usr/bin/su
- /usr/bin/less
action: member
state: absent
```
Example playbook to make sure sudocmdgroup is absent:
```yaml
---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
# Ensure sudocmdgroup is absent
- ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
name: group01
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of sudocmdgroup name strings. | no
`description` | The sudocmdgroup description string. | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`sudocmd` | List of sudocmdgroup name strings assigned to this sudocmdgroup. | no
`action` | Work on sudocmdgroup or member level. It can be on of `member` or `sudocmdgroup` and defaults to `sudocmdgroup`. | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | no
Authors
=======
Rafael Guterres Jeffman
ansible-freeipa-master/README-sudorule.md 0000664 0000000 0000000 00000011326 14600563364 0020526 0 ustar 00root root 0000000 0000000 Sudorule module
===============
Description
-----------
The sudorule (Sudo Rule) module allows to ensure presence and absence of Sudo Rules and host, hostgroups, users, and user groups as members of Sudo Rule.
Features
--------
* Sudo Rule management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipasudorule module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure Sudo Rule is present:
```yaml
---
- name: Playbook to handle sudorules
hosts: ipaserver
become: true
tasks:
# Ensure Sudo Rule is present
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
```
Example playbook to make sure sudocmds are present in Sudo Rule:
```yaml
---
- name: Playbook to handle sudorules
hosts: ipaserver
become: true
tasks:
# Ensure Sudo Rule is present
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
allow_sudocmd:
- /sbin/ifconfig
action: member
```
Example playbook to make sure sudocmds are not present in Sudo Rule:
```yaml
---
- name: Playbook to handle sudorules
hosts: ipaserver
become: true
tasks:
# Ensure Sudo Rule is present
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
allow_sudocmd:
- /sbin/ifconfig
action: member
state: absent
```
Example playbook to ensure a Group of RunAs User is present in sudo rule:
```yaml
---
- name: Playbook to manage sudorule member
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Ensure sudorule 'runasuser' has 'ipasuers' group as runas users.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
runasuser_group: ipausers
action: member
```
Example playbook to make sure Sudo Rule is absent:
```yaml
---
- name: Playbook to handle sudorules
hosts: ipaserver
become: true
tasks:
# Ensure Sudo Rule is present
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of sudorule name strings. | yes
`description` | The sudorule description string. | no
`usercategory` \| `usercat` | User category the rule applies to. Choices: ["all", ""] | no
`hostcategory` \| `hostcat` | Host category the rule applies to. Choices: ["all", ""] | no
`cmdcategory` \| `cmdcat` | Command category the rule applies to. Choices: ["all", ""] | no
`runasusercategory` \| `runasusercat` | RunAs User category the rule applies to. Choices: ["all", ""] | no
`runasgroupcategory` \| `runasgroupcat` | RunAs Group category the rule applies to. Choices: ["all", ""] | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`host` | List of host name strings assigned to this sudorule. | no
`hostgroup` | List of host group name strings assigned to this sudorule. | no
`hostmask` | List of host masks of allowed hosts | no
`user` | List of user name strings assigned to this sudorule. | no
`group` | List of user group name strings assigned to this sudorule. | no
`allow_sudocmd` | List of sudocmd name strings assigned to the allow group of this sudorule. | no
`deny_sudocmd` | List of sudocmd name strings assigned to the deny group of this sudorule. | no
`allow_sudocmdgroup` | List of sudocmd groups name strings assigned to the allow group of this sudorule. | no
`deny_sudocmdgroup` | List of sudocmd groups name strings assigned to the deny group of this sudorule. | no
`sudooption` \| `options` | List of options to the sudorule | no
`order` \| `sudoorder` | Integer to order the sudorule | no
`runasuser` | List of users for Sudo to execute as. | no
`runasgroup` | List of groups for Sudo to execute as. | no
`action` | Work on sudorule or member level. It can be on of `member` or `sudorule` and defaults to `sudorule`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled` or `disabled`, default: `present`. | no
Authors
=======
Rafael Jeffman
ansible-freeipa-master/README-topology.md 0000664 0000000 0000000 00000013007 14600563364 0020536 0 ustar 00root root 0000000 0000000 Topology modules
================
Description
-----------
These modules allow to manage the topology. That means that it can made sure that topology segments are present, absent or reinitialized. Also it is possible to verify topology suffixes.
Features
--------
* Topology management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipatopologysegment and ipatopologysuffix modules.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to add a topology segment with default name (cn):
```yaml
---
- name: Playbook to handle topologysegment
hosts: ipaserver
become: true
tasks:
- name: Add topology segment
ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: domain
left: ipareplica1.test.local
right: ipareplica2.test.local
state: present
```
The name (cn) can also be set if it should not be the default `{left}-to-{right}`.
Example playbook to delete a topology segment:
```yaml
---
- name: Playbook to handle topologysegment
hosts: ipaserver
become: true
tasks:
- name: Delete topology segment
ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: domain
left: ipareplica1.test.local
right: ipareplica2.test.local
state: absent
```
It is possible to either use the name (cn) or left and right nodes. If left and right nodes are used, then the name will be searched and used internally.
Example playbook to reinitialize a topology segment:
```yaml
---
- name: Playbook to handle topologysegment
hosts: ipaserver
become: true
tasks:
- name: Reinitialize topology segment
ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: domain
left: ipareplica1.test.local
right: ipareplica2.test.local
direction: left-to-right
state: reinitialized
```
It is possible to either use the name (cn) or left and right nodes. If left and right nodes are used, then the name will be searched and used internally.
Example playbook to verify a topology suffix:
```yaml
---
- name: Playbook to handle topologysuffix
hosts: ipaserver
become: true
tasks:
- name: Verify topology suffix
ipatopologysuffix:
ipaadmin_password: SomeADMINpassword
suffix: domain
state: verified
```
Example playbook to add or remove or check or reinitialize a list of topology segments:
```yaml
---
- name: Add topology segments
hosts: ipaserver
become: true
gather_facts: false
vars:
ipaadmin_password: password1
ipatopology_segments:
- {suffix: domain, left: replica1.test.local, right: replica2.test.local}
- {suffix: domain, left: replica2.test.local, right: replica3.test.local}
- {suffix: domain, left: replica3.test.local, right: replica4.test.local}
- {suffix: domain+ca, left: replica4.test.local, right: replica1.test.local}
tasks:
- name: Add topology segment
ipatopologysegment:
ipaadmin_password: "{{ ipaadmin_password }}"
suffix: "{{ item.suffix }}"
name: "{{ item.name | default(omit) }}"
left: "{{ item.left }}"
right: "{{ item.right }}"
state: present
#state: absent
#state: checked
#state: reinitialized
loop: "{{ ipatopology_segments | default([]) }}"
```
Variables
=========
ipatopologysegment
------------------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`suffix` | The topology suffix to be used, this can either be `domain`, `ca` or `domain+ca` | yes
`name` \| `cn` | The topology segment name (cn) is the unique identifier for a segment. | no
`left` \| `leftnode` | The left replication node string - an IPA server | no
`right` \| `rightnode` | The right replication node string - an IPA server | no
`direction` | The direction a segment will be reinitialized. It can either be `left-to-right` or `right-to-left` and only used with `state: reinitialized` | no
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled`, `disabled`, `checked` or `reinitialized` | yes
ipatopologysuffix
-----------------
Verify FreeIPA topology suffix
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`suffix` | The topology suffix to be used, this can either be `domain` or `ca` | yes
`state` | The state to ensure. It can only be `verified` | yes
Authors
=======
Thomas Woerner
ansible-freeipa-master/README-trust.md 0000664 0000000 0000000 00000006347 14600563364 0020054 0 ustar 00root root 0000000 0000000 Trust module
============
Description
-----------
The trust module allows to ensure presence and absence of a domain trust.
Features
--------
* Trust management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipatrust module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
* samba-4
* ipa-server-trust-ad
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to ensure a one-way trust is present:
Omitting the two_way option implies the default of one-way
```yaml
---
- name: Playbook to ensure a one-way trust is present
hosts: ipaserver
become: true
tasks:
- name: ensure the one-way trust present
ipatrust:
realm: ad.example.test
admin: Administrator
password: secret_password
state: present
```
Example playbook to ensure a two-way trust is present using a shared-secret:
```yaml
---
- name: Playbook to ensure a two-way trust is present
hosts: ipaserver
become: true
tasks:
- name: ensure the two-way trust is present
ipatrust:
realm: ad.example.test
trust_secret: my_share_Secret
two_way: True
state: present
```
Example playbook to ensure a trust is absent:
```yaml
---
- name: Playbook to ensure a trust is absent
hosts: ipaserver
become: true
tasks:
- name: ensure the trust is absent
ipatrust:
realm: ad.example.test
state: absent
```
This will only delete the ipa-side of the trust and it does NOT delete the id-range that matches the trust,
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`realm` | The realm name string. | yes
`admin` | Active Directory domain administrator string. | no
`password` | Active Directory domain administrator's password string. | no
`server` | Domain controller for the Active Directory domain string. | no
`trust_secret` | Shared secret for the trust string. | no
`trust_type` | Trust type. Currently, only 'ad' for Active Directory is supported. | no
`base_id` | First posix id for the trusted domain integer. | no
`range_size` | Size of the ID range reserved for the trusted domain integer. | no
`range_type` | Type of trusted domain ID range, It can be one of `ipa-ad-trust` or `ipa-ad-trust-posix`and defaults to `ipa-ad-trust`. | no
`two_way` | Establish bi-directional trust. By default trust is inbound one-way only. (bool) | no
`external` | Establish external trust to a domain in another forest. The trust is not transitive beyond the domain. (bool) | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | yes
Authors
=======
Rob Verduijn
ansible-freeipa-master/README-user.md 0000664 0000000 0000000 00000035746 14600563364 0017656 0 ustar 00root root 0000000 0000000 User module
===========
Description
-----------
The user module allows to ensure presence, absence, disablement, unlocking and undeletion of users.
The user module is as compatible as possible to the Ansible upstream `ipa_user` module, but additionally offers to preserve delete, enable, disable, unlock and undelete users.
Features
--------
* User management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipauser module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to ensure a user is present:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Ensure user pinky is present
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
first: pinky
last: Acme
uid: 10001
gid: 100
gecos: "The Pinky"
phone: "+555123457"
email: pinky@acme.com
passwordexpiration: "2023-01-19 23:59:59"
password: "no-brain"
update_password: on_create
# Ensure user brain is present
- ipauser:
ipaadmin_password: SomeADMINpassword
name: brain
first: brain
last: Acme
```
`update_password` controls if a password for a user will be set in present state only on creation or every time (always).
These two `ipauser` module calls can be combined into one with the `users` variable:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Ensure users pinky and brain are present
- ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: pinky
first: pinky
last: Acme
uid: 10001
gid: 100
phone: "+555123457"
email: pinky@acme.com
passwordexpiration: "2023-01-19 23:59:59"
password: "no-brain"
- name: brain
first: brain
last: Acme
update_password: on_create
```
You can also alternatively use a json file containing the users, here `users_present.json`:
```json
{
"users": [
{
"name": "user1",
"first": "First 1",
"last": "Last 1"
},
{
"name": "user2",
"first": "First 2",
"last": "Last 2"
},
...
]
}
```
And ensure the presence of the users with this example playbook:
```yaml
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include users_present.json
include_vars:
file: users_present.json
- name: Users present
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ users }}"
```
Ensure user pinky is present with a generated random password and print the random password:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Ensure user pinky is present with a random password
- ipauser:
ipaadmin_password: SomeADMINpassword
name: brain
first: brain
last: Acme
random: yes
register: ipauser
- name: Print generated random password
debug:
var: ipauser.user.randompassword
```
Ensure users pinky and brain are present with a generated random password and print the random passwords:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Ensure users pinky and brain are present with random password
- ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: pinky
first: pinky
last: Acme
uid: 10001
gid: 100
phone: "+555123457"
email: pinky@acme.com
passwordexpiration: "2023-01-19 23:59:59"
password: "no-brain"
- name: brain
first: brain
last: Acme
register: ipauser
- name: Print generated random password of pinky
debug:
var: ipauser.user.pinky.randompassword
- name: Print generated random password of brain
debug:
var: ipauser.user.brain.randompassword
```
Example playbook to delete a user, but preserve it:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Remove but preserve user pinky
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
preserve: yes
state: absent
```
This can also be done with the `users` variable containing only names, this can be combined into one module call:
Example playbook to delete a user, but preserve it using the `users` variable:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Remove but preserve user pinky
- ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: pinky
preserve: yes
state: absent
```
This can also be done as an alternative with the `users` variable containing only names.
Example playbook to undelete a preserved user.
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Undelete preserved user pinky
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: undeleted
```
This can also be done as an alternative with the `users` variable containing only names.
Example playbook to disable a user:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Disable user pinky
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: disabled
```
This can also be done as an alternative with the `users` variable containing only names.
Example playbook to enable users:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Enable user pinky and brain
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky,brain
state: enabled
```
This can also be done as an alternative with the `users` variable containing only names.
Example playbook to rename users:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Rename user pinky to reddy
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
rename: reddy
state: enabled
```
Example playbook to unlock users:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Unlock user pinky and brain
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky,brain
state: unlocked
```
Example playbook to ensure users are absent:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Ensure users pinky and brain are absent
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky,brain
state: absent
```
This can also be done as an alternative with the `users` variable containing only names.
Example playbook to ensure users are absent:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Ensure users pinky and brain are absent
- ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: pinky
- name: brain
state: absent
```
When using FreeIPA 4.8.0+, SMB logon script, profile, home directory and home drive can be set for users.
In the example playbook to set SMB attributes note that `smb_profile_path` and `smb_home_dir` use paths in UNC format, which includes backslashes ('\\`). If the paths are quoted, the backslash needs to be escaped becoming "\\", so the path `\\server\dir` becomes `"\\\\server\\dir"`. If the paths are unquoted the slashes do not have to be escaped.
The YAML specification states that a colon (':') is a key separator and a dash ('-') is an item marker, only with a space after them, so using both unquoted as part of a path should not be a problem. If a space is needed after a colon or a dash, then a quoted string must be used as in `"user - home"`. For the `smb_home_drive` attribute is is recomended that a quoted string is used, to improve readability.
Example playbook to set SMB attributes:
```yaml
---
- name: Plabook to handle users
hosts: ipaserver
become: false
tasks:
- name: Ensure user 'smbuser' is present with smb attributes
ipauser:
ipaadmin_password: SomeADMINpassword
name: smbuser
first: SMB
last: User
smb_logon_script: N:\logonscripts\startup
smb_profile_path: \\server\profiles\some_profile
smb_home_dir: \\users\home\smbuser
smb_home_drive: "U:"
```
Variables
=========
**General Variables:**
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` | The list of user name strings. `name` with *user variables* or `users` containing *user variables* need to be used. | no
**User variables** | Only used with `name` variable in the first level. | no
`users` | The list of user dicts. Each `users` dict entry can contain **user variables**.
There is one required option in the `users` dict:| no
| `name` - The user name string of the entry. | yes
| **User variables** | no
`preserve` | Delete a user, keeping the entry available for future use. (bool) | no
`update_password` | Set password for a user in present state only on creation or always. It can be one of `always` or `on_create` and defaults to `always`. | no
`preserve` | Delete a user, keeping the entry available for future use. (bool) | no
`action` | Work on user or member level. It can be on of `member` or `user` and defaults to `user`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled`, `disabled`, `renamed`, `unlocked` or `undeleted`, default: `present`. Only `names` or `users` with only `name` set are allowed if state is not `present`. | yes
**User Variables:**
Variable | Description | Required
-------- | ----------- | --------
`first` \| `givenname` | The first name string. Required if user does not exist. | no
`last` \| `sn` | The last name string. Required if user does not exist. | no
`fullname` \| `cn` | The full name string. | no
`displayname` | The display name string. | no
`homedir` | The home directory string. | no
`shell` \| `loginshell` | The login shell string. | no
`email` | List of email address strings. | no
`principal` \| `principalnam` \| `krbprincipalname` | The kerberos principal sptring. | no
`principalexpiration` \| `krbprincipalexpiration` | The kerberos principal expiration date. Possible formats: `YYYYMMddHHmmssZ`, `YYYY-MM-ddTHH:mm:ssZ`, `YYYY-MM-ddTHH:mmZ`, `YYYY-MM-ddZ`, `YYYY-MM-dd HH:mm:ssZ` or `YYYY-MM-dd HH:mmZ`. The trailing 'Z' can be skipped. | no
`passwordexpiration` \| `krbpasswordexpiration` | The kerberos password expiration date. Possible formats: `YYYYMMddHHmmssZ`, `YYYY-MM-ddTHH:mm:ssZ`, `YYYY-MM-ddTHH:mmZ`, `YYYY-MM-ddZ`, `YYYY-MM-dd HH:mm:ssZ` or `YYYY-MM-dd HH:mmZ`. The trailing 'Z' can be skipped. Only usable with IPA versions 4.7 and up. | no
`password` | The user password string. | no
`random` | Generate a random user password | no
`uid` \| `uidnumber` | User ID Number (system will assign one if not provided). | no
`gid` \| `gidnumber` | Group ID Number. | no
`gecos` | GECOS | no
`street` | Street address | no
`city` | City | no
`userstate` \| `st` | State/Province | no
`postalcode` \| `zip` | Postalcode/ZIP | no
`phone` \| `telephonenumber` | List of telephone number strings, | no
`mobile` | List of mobile telephone number strings. | no
`pager` | List of pager number strings. | no
`fax` \| `facsimiletelephonenumber` | List of fax number strings. | no
`orgunit` | The Organisation unit. | no
`title` | The job title string. | no
`manager` | List of manager user names. | no
`carlicense` | List of car licenses. | no
`sshpubkey` \| `ipasshpubkey` | List of SSH public keys. | no
`userauthtype` \| `ipauserauthtype` | List of supported user authentication types. Choices: `password`, `radius`, `otp`, `pkinit`, `hardened`, `idp` and `""`. An additional check ensures that only types can be used that are supported by the IPA version. Use empty string to reset userauthtype to the initial value. | no
`userclass` | User category. (semantics placed on this attribute are for local interpretation). | no
`radius` | RADIUS proxy configuration | no
`radiususer` | RADIUS proxy username | no
`departmentnumber` | Department Number | no
`employeenumber` | Employee Number | no
`employeetype` | Employee Type | no
`preferredlanguage` | Preferred Language | no
`idp` \| `ipaidpconfiglink` | External IdP configuration | no
`idp_user_id` \| `ipaidpsub` | A string that identifies the user at external IdP | no
`certificate` | List of base-64 encoded user certificates. | no
`certmapdata` | List of certificate mappings. Either `data` or `certificate` or `issuer` together with `subject` need to be specified. Only usable with IPA versions 4.5 and up.
Options: | no
| `certificate` - Base-64 encoded user certificate, not usable with other certmapdata options. | no
| `issuer` - Issuer of the certificate, only usable together with `usbject` option. | no
| `subject` - Subject of the certificate, only usable together with `issuer` option. | no
| `data` - Certmap data, not usable with other certmapdata options. | no
`noprivate` | Do not create user private group. (bool) | no
`smb_logon_script` \| `ipantlogonscript` | SMB logon script path. Requires FreeIPA version 4.8.0+. | no
`smb_profile_path:` \| `ipantprofilepath` | SMB profile path, in UNC format. Requires FreeIPA version 4.8.0+. | no
`smb_home_dir` \| `ipanthomedirectory` | SMB Home Directory, in UNC format. Requires FreeIPA version 4.8.0+. | no
`smb_home_drive` \| `ipanthomedirectorydrive` | SMB Home Directory Drive, a single upercase letter (A-Z) followed by a colon (:), for example "U:". Requires FreeIPA version 4.8.0+. | no
`rename` \| `new_name` | Rename the user object to the new name string. Only usable with `state: renamed`. | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
Return Values
=============
There are only return values if one or more random passwords have been generated.
Variable | Description | Returned When
-------- | ----------- | -------------
`user` | User dict with random password. (dict)
Options: | If random is yes and user did not exist or update_password is yes
| `randompassword` - The generated random password | If only one user is handled by the module without using the `users` parameter.
| `name` - The user name of the user that got a new random password. (dict)
Options:
`randompassword` - The generated random password | If several users are handled by the module with the `users` parameter.
Authors
=======
- Thomas Woerner
- Rafael Jeffman
ansible-freeipa-master/README-vault.md 0000664 0000000 0000000 00000016475 14600563364 0020031 0 ustar 00root root 0000000 0000000 Vault module
===================
Description
-----------
The vault module allows to ensure presence and absence of vault and members of vaults.
The vault module is as compatible as possible to the Ansible upstream `ipa_vault` module, and additionally offers to make sure that vault members, groups and owners are present or absent in a vault, and allow the archival of data in vaults.
Features
--------
* Vault management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipavault module.
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
* KRA service must be enabled
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure vault is present (by default, vault type is `symmetric`):
```yaml
---
- name: Playbook to handle vaults
hosts: ipaserver
become: true
tasks:
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
description: A standard private vault.
```
Example playbook to make sure that a vault and its members are present:
```yaml
---
- name: Playbook to handle vaults
hosts: ipaserver
become: true
tasks:
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
users: user01
```
`action` controls if the vault, data, member or owner will be handled. To add or remove members or vault data, set `action` to `member`.
Example playbook to make sure that a vault member is present in vault:
```yaml
---
- name: Playbook to handle vaults
hosts: ipaserver
become: true
tasks:
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
users: user01
action: member
```
Example playbook to make sure that a vault owner is absent in vault:
```yaml
---
- name: Playbook to handle vaults
hosts: ipaserver
become: true
tasks:
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
owner: user01
action: member
state: absent
```
Example playbook to make sure vault data is present in a symmetric vault:
```yaml
---
- name: Playbook to handle vaults
hosts: ipaserver
become: true
tasks:
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
password: SomeVAULTpassword
data: >
Data archived.
More data archived.
action: member
```
When retrieving data from a vault, it is recommended that `no_log: yes` is used, so that sensitive data stored in a vault is not logged by Ansible. The data is returned in a dict `vault`, in the field `data` (e.g. `result.vault.data`). An example playbook to retrieve data from a symmetric vault:
```yaml
---
- name: Playbook to handle vaults
hosts: ipaserver
become: true
tasks:
- name: Retrieve data from vault and register it in 'ipavault'
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
password: SomeVAULTpassword
state: retrieved
no_log: yes
register: ipavault
- name: Print retrieved data from vault
debug:
var: ipavault.vault.data
```
Example playbook to make sure vault data is absent in a symmetric vault:
```yaml
---
- name: Playbook to handle vaults
hosts: ipaserver
become: true
tasks:
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
password: SomeVAULTpassword
action: member
state: absent
```
Example playbook to change the password of a symmetric:
```yaml
---
- name: Playbook to handle vaults
hosts: ipaserver
become: true
tasks:
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
old_password: SomeVAULTpassword
new_password: SomeNEWpassword
```
Example playbook to make sure vault is absent:
```yaml
---
- name: Playbook to handle vaults
hosts: ipaserver
become: true
tasks:
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
state: absent
register: result
- debug:
msg: "{{ result.vault.data }}"
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaapi_context` | The context in which the module will execute. Currently only `client` is supported by this module, and use of `server` will raise a failure. | no
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no
`name` \| `cn` | The list of vault name strings. | yes
`description` | The vault description string. | no
`password` \| `vault_password` \| `ipavaultpassword` \| `old_password`| Vault password. | no
`password_file` \| `vault_password_file` \| `old_password_file`| File containing Base64 encoded Vault password. | no
`new_password` | Vault new password. | no
`new_password_file` | File containing Base64 encoded new Vault password. | no
`public_key ` \| `vault_public_key` \| `ipavaultpublickey` \| `new_public_key` | Base64 encoded vault public key. | no
`public_key_file` \| `vault_public_key_file` \| `new_public_key_file` | Path to file with public key. | no
`private_key `\| `vault_private_key` \| `ipavaultprivatekey` | Base64 encoded vault private key. Used only to retrieve data. | no
`private_key_file` \| `vault_private_key_file` | Path to file with private key. Used only to retrieve data. | no
`salt` \| `vault_salt` \| `ipavaultsalt` | Vault salt. | no
`vault_type` \| `ipavaulttype` | Vault types are based on security level. It can be one of `standard`, `symmetric` or `asymmetric`, default: `symmetric` | no
`username` \| `user` | Any user can own one or more user vaults. | no
`service` | Any service can own one or more service vaults. | no
`shared` | Vault is shared. Default to false. (bool) | no
`users` | List of users that are members of the vault. | no
`groups` | List of groups that are member of the vault. | no
`services` | List of services that are member of the vault. | no
`owners` \| `ownerusers` | List of users that are owners of the vault. | no
`ownergroups` | List of groups that are owners of the vault. | no
`ownerservices` | List of services that are owners of the vault. | no
`data` \|`vault_data` \| `ipavaultdata` | Data to be stored in the vault. | no
`in` \| `datafile_in` | Path to file with data to be stored in the vault. | no
`out` \| `datafile_out` | Path to file to store data retrieved from the vault. | no
`action` | Work on vault or member level. It can be on of `member` or `vault` and defaults to `vault`. | no
`state` | The state to ensure. It can be one of `present`, `absent` or `retrieved`, default: `present`. | no
Return Values
=============
There is only a return value if `state` is `retrieved`.
Variable | Description | Returned When
-------- | ----------- | -------------
`vault` | Vault dict with archived data. (dict)
Options: | If `state` is `retrieved` and `out` is not defined.
| `data` - The vault data. | Always
Notes
=====
ipavault uses a client context to execute, and it might affect execution time.
Authors
=======
Rafael Jeffman
ansible-freeipa-master/README.md 0000664 0000000 0000000 00000037356 14600563364 0016701 0 ustar 00root root 0000000 0000000 FreeIPA Ansible collection
==========================
This repository contains [Ansible](https://www.ansible.com/) roles and playbooks to install and uninstall [FreeIPA](https://www.freeipa.org/) `servers`, `replicas` and `clients`. Also modules for group, host, topology and user management.
**Note**: The Ansible playbooks and roles require a configured Ansible environment where the Ansible nodes are reachable and are properly set up to have an IP address and a working package manager.
Features
--------
* Server, replica and client deployment
* Cluster deployments: Server, replicas and clients in one playbook
* One-time-password (OTP) support for client installation
* Repair mode for clients
* Backup and restore, also to and from controller
* Smartcard setup for servers and clients
* Modules for automembership rule management
* Modules for automount key management
* Modules for automount location management
* Modules for automount map management
* Modules for certificate management
* Modules for config management
* Modules for delegation management
* Modules for dns config management
* Modules for dns forwarder management
* Modules for dns record management
* Modules for dns zone management
* Modules for group management
* Modules for hbacrule management
* Modules for hbacsvc management
* Modules for hbacsvcgroup management
* Modules for host management
* Modules for hostgroup management
* Modules for idoverridegroup management
* Modules for idoverrideuser management
* Modules for idp management
* Modules for idrange management
* Modules for idview management
* Modules for location management
* Modules for netgroup management
* Modules for permission management
* Modules for privilege management
* Modules for pwpolicy management
* Modules for role management
* Modules for self service management
* Modules for server management
* Modules for service management
* Modules for service delegation rule management
* Modules for service delegation target management
* Modules for sudocmd management
* Modules for sudocmdgroup management
* Modules for sudorule management
* Modules for topology management
* Modules for trust management
* Modules for user management
* Modules for vault management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.6 and up are supported by all roles.
The client role supports versions 4.4 and up, the server role is working with versions 4.5 and up, the replica role is currently only working with versions 4.6 and up.
Supported Distributions
-----------------------
* RHEL/CentOS 7.4+
* Fedora 26+
* Ubuntu
* Debian 10+ (ipaclient only, no server or replica!)
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
* Supported distribution (needed for package installation only, see above)
Limitations
-----------
**External signed CA**
External signed CA is now supported. But the currently needed two step process is an issue for the processing in a simple playbook.
Work is planned to have a new method to handle CSR for external signed CAs in a separate step before starting the server installation.
Usage
=====
How to use ansible-freeipa
--------------------------
**GIT repo**
The simplest method for now is to clone this repository on the controller from github directly and to start the deployment from the ansible-freeipa directory:
```bash
git clone https://github.com/freeipa/ansible-freeipa.git
cd ansible-freeipa
```
You can use the roles directly within the top directory of the git repo, but to be able to use the management modules in the plugins subdirectory, you have to either adapt `ansible.cfg` or create links for the roles, modules or directories.
You can either adapt ansible.cfg:
```
roles_path = /my/dir/ansible-freeipa/roles
library = /my/dir/ansible-freeipa/plugins/modules
module_utils = /my/dir/ansible-freeipa/plugins/module_utils
```
Or you can link the directories:
```
ansible-freeipa/roles to ~/.ansible/
ansible-freeipa/plugins/modules to ~/.ansible/plugins/
ansible-freeipa/plugins/module_utils to ~/.ansible/plugins/
```
**RPM package**
There are RPM packages available for Fedora 29+. These are installing the roles and modules into the global Ansible directories for `roles`, `plugins/modules` and `plugins/module_utils` in the `/usr/share/ansible` directory. Therefore is it possible to use the roles and modules without adapting the names like it is done in the example playbooks.
**Ansible Galaxy**
This command will get the whole collection from galaxy:
```bash
ansible-galaxy collection install freeipa.ansible_freeipa
```
Ansible galaxy does not support the use of dash ('-') in a name and is automatically replacing this with an underscore ('\_'). Therefore the name is `ansible_freeipa`. The ansible_freeipa collection will be placed in the directory `~/.ansible/collections/ansible_collections/freeipa/ansible_freeipa` where it will be automatically be found for this user.
Ansible inventory file
----------------------
The most important parts of the inventory file is the definition of the nodes, settings and the management modules. Please remember to use [Ansible Vault](https://docs.ansible.com/ansible/latest/user_guide/vault.html) for passwords. The examples here are not using vault for better readability.
**Master server**
The master server is defined within the ```[ipaserver]``` group:
```yaml
[ipaserver]
ipaserver.test.local
```
There are variables that need to be set like ```domain```, ```realm```, ```admin password``` and ```dm password```. These can be set in the ```[ipaserver:vars]``` section:
```yaml
[ipaserver:vars]
ipaadmin_password=ADMPassword1
ipadm_password=DMPassword1
ipaserver_domain=test.local
ipaserver_realm=TEST.LOCAL
```
The admin principal is ```admin``` by default. Please set ```ipaadmin_principal``` if you need to change it.
You can also add more setting here, like for example to enable the DNS server or to set auto-forwarders:
```yaml
[ipaserver:vars]
ipaserver_setup_dns=yes
ipaserver_auto_forwarders=yes
```
But also to skip package installation or firewalld configuration:
```yaml
[ipaserver:vars]
ipaserver_install_packages=no
ipaserver_setup_firewalld=no
```
The installation of packages and also the configuration of the firewall are by default enabled.
Note that it is not enough to mask systemd firewalld service to skip the firewalld configuration. You need to set the variable to `no`.
For more server settings, please have a look at the [server role documentation](roles/ipaserver/README.md).
**Replica**
The replicas are defined within the ```[ipareplicas]``` group:
```yaml
[ipareplicas]
ipareplica1.test.local
ipareplica2.test.local
```
If the master server is already deployed and there are DNS txt records to be able to auto-detect the server, then it is not needed to set ```domain``` or ```realm``` for the replica deployment. But it might be needed to set the master server of a replica because of the topology. If this is needed, it can be set either in the ```[ipareplicas:vars]``` section if it will apply to all the replicas in the ```[ipareplicas]``` group or it is possible to set this also per replica in the ```[ipareplicas]``` group:
```yaml
[ipareplicas]
ipareplica1.test.local
ipareplica2.test.local ipareplica_servers=ipareplica1.test.local
```
This will create a chain from ```ipaserver.test.local <- ipareplica1.test.local <- ipareplica2.test.local```.
If you need to set more than one server for a replica (for fallbacks etc.), simply use a comma separated list for ```ipareplica_servers```:
```yaml
[ipareplicas_tier1]
ipareplica1.test.local
[ipareplicas_tier2]
ipareplica2.test.local ipareplica_servers=ipareplica1.test.local,ipaserver.test.local
```
The first entry in ```ipareplica_servers``` will be used as the master.
In this case you need to have separate tasks in the playbook to first deploy replicas from tier1 and then replicas from tier2:
```yaml
---
- name: Playbook to configure IPA replicas (tier1)
hosts: ipareplicas_tier1
become: true
roles:
- role: ipareplica
state: present
- name: Playbook to configure IPA replicas (tier2)
hosts: ipareplicas_tier2
become: true
roles:
- role: ipareplica
state: present
```
You can add settings for replica deployment:
```yaml
[ipareplicas:vars]
ipaadmin_password=ADMPassword1
ipadm_password=DMPassword1
ipaserver_domain=test.local
ipaserver_realm=TEST.LOCAL
```
You can also add more setting here, like for example to setup DNS or to enable auto-forwarders:
```yaml
[ipareplica:vars]
ipaserver_setup_dns=yes
ipaserver_auto_forwarders=yes
```
If you need to skip package installation or firewalld configuration:
```yaml
[ipareplicas:vars]
ipareplica_install_packages=no
ipareplica_setup_firewalld=no
```
The installation of packages and also the configuration of the firewall are by default enabled.
Note that it is not enough to mask systemd firewalld service to skip the firewalld configuration. You need to set the variable to `no`.
For more replica settings, please have a look at the [replica role documentation](roles/ipareplica/README.md).
**Client**
Clients are defined within the [ipaclients] group:
```yaml
[ipaclients]
ipaclient1.test.local
ipaclient2.test.local
ipaclient3.test.local
ipaclient4.test.local
```
For simple setups or in defined client environments it might not be needed to set domain or realm for the replica deployment. But it might be needed to set the master server of a client because of the topology. If this is needed, it can be set either in the [ipaclients:vars} section if it will apply to all the clients in the [ipaclients] group or it is possible to set this also per client in the [ipaclients] group:
```yaml
[ipaclients]
ipaclient1.test.local ipaclient_servers=ipareplica1.test.local
ipaclient2.test.local ipaclient_servers=ipareplica1.test.local
ipaclient3.test.local ipaclient_servers=ipareplica2.test.local
ipaclient4.test.local ipaclient_servers=ipareplica2.test.local
```
If you need to set more than one server for a client (for fallbacks etc.), simply use a comma separated list for ```ipaclient_servers```.
You can add settings for client deployment:
```yaml
[ipaclients:vars]
ipaadmin_password=ADMPassword1
ipaserver_domain=test.local
ipaserver_realm=TEST.LOCAL
```
For enhanced security it is possible to use a auto-generated one-time-password (OTP). This will be generated on the (first) server.
To enable the generation of the one-time-password:
```yaml
[ipaclients:vars]
ipaclient_use_otp=yes
```
For more client settings, please have a look at the [client role documentation](roles/ipaclient/README.md).
**Cluster**
If you want to deploy more than a master server at once, then it will be good to define a new group like ```[ipacluster]``` that contains all the other groups ```[ipaserver]```, ```[ipareplicas]``` and ```[ipaclients]```. This way it is not needed to set ```domain```, ```realm```, ```admin password``` or ```dm password``` for the single groups:
```yaml
[ipacluster:children]
ipaserver
ipareplicas
ipaclients
[ipacluster:vars]
ipaadmin_password=ADMPassword1
ipadm_password=DMPassword1
ipaserver_domain=test.local
ipaserver_realm=TEST.LOCAL
```
All these settings will be available in the ```[ipaserver]```, ```[ipareplicas]``` and ```[ipaclient]``` groups.
**Topology**
With this playbook it is possible to add a list of topology segments using the `ipatopologysegment` module.
```yaml
---
- name: Add topology segments
hosts: ipaserver
become: true
gather_facts: false
vars:
ipaadmin_password: password1
ipatopology_segments:
- {suffix: domain, left: replica1.test.local, right: replica2.test.local}
- {suffix: domain, left: replica2.test.local, right: replica3.test.local}
- {suffix: domain, left: replica3.test.local, right: replica4.test.local}
- {suffix: domain+ca, left: replica4.test.local, right: replica1.test.local}
tasks:
- name: Add topology segment
ipatopologysegment:
password: "{{ ipaadmin_password }}"
suffix: "{{ item.suffix }}"
name: "{{ item.name | default(omit) }}"
left: "{{ item.left }}"
right: "{{ item.right }}"
#state: present
#state: absent
#state: checked
state: reinitialized
loop: "{{ ipatopology_segments | default([]) }}"
```
Playbooks
=========
The playbooks needed to deploy or undeploy servers, replicas and clients are part of the repository and placed in the playbooks folder. There are also playbooks to deploy and undeploy clusters. With them it is only needed to add an inventory file:
```
playbooks\
install-client.yml
install-cluster.yml
install-replica.yml
install-server.yml
uninstall-client.yml
uninstall-cluster.yml
uninstall-replica.yml
uninstall-server.yml
```
How to deploy a master server
-----------------------------
```bash
ansible-playbook -v -i inventory/hosts install-server.yml
```
This will deploy the master server defined in the inventory file.
If Ansible Vault is used for passwords, then it is needed to adapt the playbooks in this way:
```yaml
---
- name: Playbook to configure IPA servers
hosts: ipaserver
become: true
vars_files:
- playbook_sensitive_data.yml
roles:
- role: ipaserver
state: present
```
It is also needed to provide the vault password file on the ansible-playbook command line:
```bash
ansible-playbook -v -i inventory/hosts --vault-password-file .vaul_pass.txt install-server.yml
```
How to deploy a replica
-----------------------
```bash
ansible-playbook -v -i inventory/hosts install-replica.yml
```
This will deploy the replicas defined in the inventory file.
How to setup a client
---------------------
```bash
ansible-playbook -v -i inventory/hosts install-client.yml
```
This will deploy the clients defined in the inventory file.
How to deploy a cluster
-----------------------
```bash
ansible-playbook -v -i inventory/hosts install-cluster.yml
```
This will deploy the server, replicas and clients defined in the inventory file.
Roles
=====
* [Server](roles/ipaserver/README.md)
* [Replica](roles/ipareplica/README.md)
* [Client](roles/ipaclient/README.md)
* [Backup](roles/ipabackup/README.md)
* [SmartCard server](roles/ipasmartcard_server/README.md)
* [SmartCard client](roles/ipasmartcard_client/README.md)
Modules in plugin/modules
=========================
* [ipaautomember](README-automember.md)
* [ipaautomountkey](README-automountkey.md)
* [ipaautomountlocation](README-automountlocation.md)
* [ipaautomountmap](README-automountmap.md)
* [ipacert](README-cert.md)
* [ipaconfig](README-config.md)
* [ipadelegation](README-delegation.md)
* [ipadnsconfig](README-dnsconfig.md)
* [ipadnsforwardzone](README-dnsforwardzone.md)
* [ipadnsrecord](README-dnsrecord.md)
* [ipadnszone](README-dnszone.md)
* [ipagroup](README-group.md)
* [ipahbacrule](README-hbacrule.md)
* [ipahbacsvc](README-hbacsvc.md)
* [ipahbacsvcgroup](README-hbacsvcgroup.md)
* [ipahost](README-host.md)
* [ipahostgroup](README-hostgroup.md)
* [idoverridegroup](README-idoverridegroup.md)
* [idoverrideuser](README-idoverrideuser.md)
* [idp](README-idp.md)
* [idrange](README-idrange.md)
* [idview](README-idview.md)
* [ipalocation](README-location.md)
* [ipanetgroup](README-netgroup.md)
* [ipapermission](README-permission.md)
* [ipaprivilege](README-privilege.md)
* [ipapwpolicy](README-pwpolicy.md)
* [iparole](README-role.md)
* [ipaselfservice](README-selfservice.md)
* [ipaserver](README-server.md)
* [ipaservice](README-service.md)
* [ipaservicedelegationrule](README-servicedelegationrule.md)
* [ipaservicedelegationtarget](README-servicedelegationtarget.md)
* [ipasudocmd](README-sudocmd.md)
* [ipasudocmdgroup](README-sudocmdgroup.md)
* [ipasudorule](README-sudorule.md)
* [ipatopologysegment](README-topology.md)
* [ipatopologysuffix](README-topology.md)
* [ipatrust](README-trust.md)
* [ipauser](README-user.md)
* [ipavault](README-vault.md)
If you want to write a new module please read [writing a new module](plugins/modules/README.md).
ansible-freeipa-master/galaxy.yml 0000664 0000000 0000000 00000001105 14600563364 0017411 0 ustar 00root root 0000000 0000000 ---
namespace: "freeipa"
name: "ansible_freeipa"
version: "A.B.C"
description: "Ansible roles and modules for FreeIPA"
authors:
- "Thomas Woerner "
repository: "https://github.com/freeipa/ansible-freeipa"
documentation: "https://github.com/freeipa/ansible-freeipa/blob/master/README.md"
homepage: "https://github.com/freeipa/ansible-freeipa"
issues: "https://github.com/freeipa/ansible-freeipa/issues"
readme: "README.md"
license:
- "GPL-3.0-or-later"
tags:
- "linux"
- "system"
- "identity"
- "ipa"
- "freeipa"
- "cluster"
- "collection"
ansible-freeipa-master/inventory/ 0000775 0000000 0000000 00000000000 14600563364 0017441 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/inventory/hosts 0000664 0000000 0000000 00000001101 14600563364 0020515 0 ustar 00root root 0000000 0000000 [ipaclients]
ipaclient1.mine.dom
#ipaclient2.mine.dom
#ipaclient3.mine.dom
#ipaclient4.mine.dom
#ipaclient5.mine.dom
ipaclient6.mine.dom
ipaclient7.mine.dom
#[ipaservers]
#ipa.mine.dom
[ipaclients:vars]
#ipaclient_keytab=/tmp/krb5.keytab
#ipaclient_domain=mine.dom
#ipaclient_realm=MINE.DOM
#ipaadmin_principal=admin
#ipaadmin_password=password1
#ipaclient_use_otp=yes
#ipaclient_force_join=yes
#ipaclient_kinit_attempts=3
#ipaclient_mkhomedir=yes
#ipaadmin_principal=admin
#ipaclient_use_otp=yes
#ipaclient_force_join=yes
#ipaclient_use_otp=yes
ipaclient_allow_repair=yes
ansible-freeipa-master/inventory/hosts.cluster 0000664 0000000 0000000 00000001004 14600563364 0022177 0 ustar 00root root 0000000 0000000 [ipaserver]
ipaserver.test.local
[ipaserver:vars]
#ipaserver_setup_dns=yes
#ipaserver_auto_forwarders=yes
#ipaserver_no_firewalld=no
[ipareplicas]
ipareplica1.test.local
[ipareplicas:vars]
ipaclient_force_join=yes
[ipaclients]
ipaclient1.test.local
ipaclient2.test.local
[ipaclients:vars]
#ipaclient_use_otp=yes
ipaclient_allow_repair=yes
[ipa:children]
ipaserver
ipareplicas
ipaclients
[ipa:vars]
ipaadmin_password=password1
ipadm_password=password1
ipaserver_domain=test.local
ipaserver_realm=TEST.LOCAL
ansible-freeipa-master/inventory/hosts.replica 0000664 0000000 0000000 00000000252 14600563364 0022141 0 ustar 00root root 0000000 0000000 [ipaservers]
ipaserver.test.local
[ipareplicas]
ipareplica1.test.local
[ipareplicas:vars]
ipaadmin_password=password1
ipadm_password=password1
ipaclient_force_join=yes
ansible-freeipa-master/meta/ 0000775 0000000 0000000 00000000000 14600563364 0016332 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/meta/runtime.yml 0000664 0000000 0000000 00000000037 14600563364 0020540 0 ustar 00root root 0000000 0000000 ---
requires_ansible: ">=2.13"
ansible-freeipa-master/molecule/ 0000775 0000000 0000000 00000000000 14600563364 0017211 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/c8s-build/ 0000775 0000000 0000000 00000000000 14600563364 0021003 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/c8s-build/Dockerfile 0000664 0000000 0000000 00000001573 14600563364 0023003 0 ustar 00root root 0000000 0000000 FROM quay.io/centos/centos:stream8
ENV container=docker
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/python3 \
/usr/bin/python3-config \
/usr/bin/dnf-3 \
sudo \
bash \
systemd \
procps-ng \
iproute && \
dnf clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*; \
rm -rf /var/cache/dnf/;
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]
ansible-freeipa-master/molecule/c8s-build/molecule.yml 0000664 0000000 0000000 00000000631 14600563364 0023333 0 ustar 00root root 0000000 0000000 ---
driver:
name: docker
platforms:
- name: c8s-build
image: "quay.io/centos/centos:stream8"
dockerfile: Dockerfile
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml
prerun: false
ansible-freeipa-master/molecule/c8s/ 0000775 0000000 0000000 00000000000 14600563364 0017706 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/c8s/molecule.yml 0000664 0000000 0000000 00000000631 14600563364 0022236 0 ustar 00root root 0000000 0000000 ---
driver:
name: docker
platforms:
- name: c8s
image: quay.io/ansible-freeipa/upstream-tests:c8s
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml
prerun: false
ansible-freeipa-master/molecule/c9s-build/ 0000775 0000000 0000000 00000000000 14600563364 0021004 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/c9s-build/Dockerfile 0000664 0000000 0000000 00000001535 14600563364 0023002 0 ustar 00root root 0000000 0000000 FROM quay.io/centos/centos:stream9
ENV container=docker
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/python3 \
/usr/bin/dnf-3 \
sudo \
bash \
systemd \
procps-ng \
iproute && \
dnf clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*; \
rm -rf /var/cache/dnf/;
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]
ansible-freeipa-master/molecule/c9s-build/molecule.yml 0000664 0000000 0000000 00000000631 14600563364 0023334 0 ustar 00root root 0000000 0000000 ---
driver:
name: docker
platforms:
- name: c9s-build
image: "quay.io/centos/centos:stream9"
dockerfile: Dockerfile
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml
prerun: false
ansible-freeipa-master/molecule/c9s/ 0000775 0000000 0000000 00000000000 14600563364 0017707 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/c9s/molecule.yml 0000664 0000000 0000000 00000000631 14600563364 0022237 0 ustar 00root root 0000000 0000000 ---
driver:
name: docker
platforms:
- name: c9s
image: quay.io/ansible-freeipa/upstream-tests:c9s
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml
prerun: false
ansible-freeipa-master/molecule/centos-7-build/ 0000775 0000000 0000000 00000000000 14600563364 0021745 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/centos-7-build/molecule.yml 0000664 0000000 0000000 00000000614 14600563364 0024276 0 ustar 00root root 0000000 0000000 ---
driver:
name: docker
platforms:
- name: centos-7-build
image: centos/systemd
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml
prerun: false
ansible-freeipa-master/molecule/centos-7/ 0000775 0000000 0000000 00000000000 14600563364 0020650 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/centos-7/molecule.yml 0000664 0000000 0000000 00000000643 14600563364 0023203 0 ustar 00root root 0000000 0000000 ---
driver:
name: docker
platforms:
- name: centos-7
image: quay.io/ansible-freeipa/upstream-tests:centos-7
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml
prerun: false
ansible-freeipa-master/molecule/default 0000777 0000000 0000000 00000000000 14600563364 0023230 2fedora-latest ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/fedora-latest-build/ 0000775 0000000 0000000 00000000000 14600563364 0023040 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/fedora-latest-build/Dockerfile 0000664 0000000 0000000 00000001553 14600563364 0025036 0 ustar 00root root 0000000 0000000 FROM fedora:latest
ENV container=docker
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/python3 \
/usr/bin/python3-config \
/usr/bin/dnf-3 \
sudo \
bash \
systemd \
procps-ng \
iproute && \
dnf clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*; \
rm -rf /var/cache/dnf/;
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]
ansible-freeipa-master/molecule/fedora-latest-build/molecule.yml 0000664 0000000 0000000 00000000623 14600563364 0025371 0 ustar 00root root 0000000 0000000 ---
driver:
name: docker
platforms:
- name: fedora-latest-build
image: "fedora:latest"
dockerfile: Dockerfile
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml
prerun: false
ansible-freeipa-master/molecule/fedora-latest/ 0000775 0000000 0000000 00000000000 14600563364 0021743 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/fedora-latest/molecule.yml 0000664 0000000 0000000 00000000655 14600563364 0024301 0 ustar 00root root 0000000 0000000 ---
driver:
name: docker
platforms:
- name: fedora-latest
image: quay.io/ansible-freeipa/upstream-tests:fedora-latest
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml
prerun: false
ansible-freeipa-master/molecule/fedora-rawhide-build/ 0000775 0000000 0000000 00000000000 14600563364 0023167 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/fedora-rawhide-build/Dockerfile 0000664 0000000 0000000 00000001554 14600563364 0025166 0 ustar 00root root 0000000 0000000 FROM fedora:rawhide
ENV container=docker
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/python3 \
/usr/bin/python3-config \
/usr/bin/dnf-3 \
sudo \
bash \
systemd \
procps-ng \
iproute && \
dnf clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*; \
rm -rf /var/cache/dnf/;
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]
ansible-freeipa-master/molecule/fedora-rawhide-build/molecule.yml 0000664 0000000 0000000 00000000625 14600563364 0025522 0 ustar 00root root 0000000 0000000 ---
driver:
name: docker
platforms:
- name: fedora-rawhide-build
image: "fedora:rawhide"
dockerfile: Dockerfile
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml
prerun: false
ansible-freeipa-master/molecule/fedora-rawhide/ 0000775 0000000 0000000 00000000000 14600563364 0022072 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/fedora-rawhide/molecule.yml 0000664 0000000 0000000 00000000657 14600563364 0024432 0 ustar 00root root 0000000 0000000 ---
driver:
name: docker
platforms:
- name: fedora-rawhide
image: quay.io/ansible-freeipa/upstream-tests:fedora-rawhide
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml
prerun: false
ansible-freeipa-master/molecule/resources/ 0000775 0000000 0000000 00000000000 14600563364 0021223 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/resources/playbooks/ 0000775 0000000 0000000 00000000000 14600563364 0023226 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/resources/playbooks/library 0000777 0000000 0000000 00000000000 14600563364 0030604 2../../../plugins/modules/ ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/resources/playbooks/module_utils 0000777 0000000 0000000 00000000000 14600563364 0032702 2../../../plugins/module_utils/ ustar 00root root 0000000 0000000 ansible-freeipa-master/molecule/resources/playbooks/prepare-build.yml 0000664 0000000 0000000 00000001224 14600563364 0026503 0 ustar 00root root 0000000 0000000 ---
- name: Converge
hosts: all
tasks:
- include_tasks: prepare-common.yml
- name: Ensure sudo package is installed
package:
name: sudo
- name: Ensure nss package is updated
package:
name: nss
state: latest # noqa 403
- include_role:
name: ipaserver
vars:
ipaserver_setup_dns: yes
ipaserver_setup_kra: yes
ipaserver_auto_forwarders: yes
ipaserver_no_dnssec_validation: yes
ipaserver_auto_reverse: yes
ipaadmin_password: SomeADMINpassword
ipadm_password: SomeDMpassword
ipaserver_domain: test.local
ipaserver_realm: TEST.LOCAL
ipaclient_no_ntp: yes
ansible-freeipa-master/molecule/resources/playbooks/prepare-common.yml 0000664 0000000 0000000 00000001614 14600563364 0026677 0 ustar 00root root 0000000 0000000 ---
# IPA depends on IPv6 and without it dirsrv service won't start.
- name: Ensure IPv6 is ENABLED
ansible.posix.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
sysctl_set: yes
state: present
reload: yes
with_items:
- name: net.ipv6.conf.all.disable_ipv6
value: 0
- name: net.ipv6.conf.lo.disable_ipv6
value: 0
- name: net.ipv6.conf.eth0.disable_ipv6
value: 1
# Set fs.protected_regular to 0
# This is needed in some IPA versions in order to get KRA enabled.
# See https://pagure.io/freeipa/issue/7906 for more information.
- name: stat protected_regular
ansible.builtin.stat:
path: /proc/sys/fs/protected_regular
register: result
- name: Ensure fs.protected_regular is disabled
ansible.posix.sysctl:
name: fs.protected_regular
value: 0
sysctl_set: yes
state: present
reload: yes
when: result.stat.exists
ansible-freeipa-master/molecule/resources/playbooks/prepare.yml 0000664 0000000 0000000 00000002504 14600563364 0025410 0 ustar 00root root 0000000 0000000 ---
- name: Converge
hosts: all
tasks:
- include_tasks: prepare-common.yml
# In some distros DS won't start up after reboot
# This is due to a problem in 389-ds. See tickets:
# * https://pagure.io/389-ds-base/issue/47429
# * https://pagure.io/389-ds-base/issue/51039
#
# To avoid this problem we create the directories before starting IPA.
- name: Ensure lock dirs for DS exists
ansible.builtin.file:
state: directory
owner: dirsrv
group: dirsrv
path: "{{ item }}"
mode: 0770
loop:
- /var/lock/dirsrv/
- /var/lock/dirsrv/slapd-TEST-LOCAL/
- name: Ensure IPA server is up an running
ansible.builtin.service:
name: ipa
state: started
- name: Wait for krb5dkc to be running
ansible.builtin.service_facts:
no_log: True
register: result
until: "'krb5kdc.service' in result.ansible_facts.services and \
result.ansible_facts.services['krb5kdc.service'].state == 'running'"
retries: 30
delay: 5
- name: Check if TGT is available for admin.
ansible.builtin.shell:
cmd: echo SomeADMINpassword | kinit -c ansible_freeipa_cache admin
register: result
until: not result.failed
retries: 30
delay: 5
- name: Cleanup TGT.
ansible.builtin.shell:
cmd: kdestroy -c ansible_freeipa_cache -A
ansible-freeipa-master/molecule/resources/playbooks/roles 0000777 0000000 0000000 00000000000 14600563364 0026257 2../../../roles/ ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/ 0000775 0000000 0000000 00000000000 14600563364 0017407 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/automember/ 0000775 0000000 0000000 00000000000 14600563364 0021547 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/automember/automember-default-group-not-set.yml 0000664 0000000 0000000 00000000400 14600563364 0030567 0 ustar 00root root 0000000 0000000 ---
- name: Automember default group not set
hosts: ipaserver
become: true
tasks:
- name: Ensure automember default group is not set
ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: group
default_group: ""
ansible-freeipa-master/playbooks/automember/automember-default-group-set.yml 0000664 0000000 0000000 00000000404 14600563364 0027775 0 ustar 00root root 0000000 0000000 ---
- name: Automember default group set
hosts: ipaserver
become: true
tasks:
- name: Ensure automember default group is set
ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: group
default_group: fallback_group
ansible-freeipa-master/playbooks/automember/automember-default-hostgroup-not-set.yml 0000664 0000000 0000000 00000000414 14600563364 0031472 0 ustar 00root root 0000000 0000000 ---
- name: Automember default hostgroup not set
hosts: ipaserver
become: true
tasks:
- name: Ensure automember default hostgroup is not set
ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: hostgroup
default_group: ""
ansible-freeipa-master/playbooks/automember/automember-default-hostgroup-set.yml 0000664 0000000 0000000 00000000424 14600563364 0030675 0 ustar 00root root 0000000 0000000 ---
- name: Automember default hostgroup set
hosts: ipaserver
become: true
tasks:
- name: Ensure automember default hostgroup is set
ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: hostgroup
default_group: fallback_hostgroup
ansible-freeipa-master/playbooks/automember/automember-group-absent.yml 0000664 0000000 0000000 00000000421 14600563364 0027033 0 ustar 00root root 0000000 0000000 ---
- name: Automember group absent example
hosts: ipaserver
become: true
tasks:
- name: Ensure group automember rule admins is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
name: admins
automember_type: group
state: absent
ansible-freeipa-master/playbooks/automember/automember-group-membership-all-users-rebuilt.yml 0000664 0000000 0000000 00000000432 14600563364 0033265 0 ustar 00root root 0000000 0000000 ---
- name: Automember group membership for all users rebuilt example
hosts: ipaserver
become: true
tasks:
- name: Ensure group automember rule admins is present
ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: group
state: rebuilt
ansible-freeipa-master/playbooks/automember/automember-group-membership-users-rebuilt.yml 0000664 0000000 0000000 00000000462 14600563364 0032522 0 ustar 00root root 0000000 0000000 ---
- name: Automember group membership for given users rebuilt example
hosts: ipaserver
become: true
tasks:
- name: Ensure group membership for given users has been rebuilt
ipaautomember:
ipaadmin_password: SomeADMINpassword
users:
- user1
- user2
state: rebuilt
ansible-freeipa-master/playbooks/automember/automember-group-orphans-removed.yml 0000664 0000000 0000000 00000000421 14600563364 0030670 0 ustar 00root root 0000000 0000000 ---
- name: Automember orphan group rules are removed example
hosts: ipaserver
become: true
tasks:
- name: Ensure orphan group rules are removed
ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: group
state: orphans_removed
ansible-freeipa-master/playbooks/automember/automember-group-present.yml 0000664 0000000 0000000 00000000424 14600563364 0027242 0 ustar 00root root 0000000 0000000 ---
- name: Automember group present example
hosts: ipaserver
become: true
tasks:
- name: Ensure group automember rule admins is present
ipaautomember:
ipaadmin_password: SomeADMINpassword
name: admins
automember_type: group
state: present
ansible-freeipa-master/playbooks/automember/automember-hostgroup-absent.yml 0000664 0000000 0000000 00000000445 14600563364 0027737 0 ustar 00root root 0000000 0000000 ---
- name: Automember hostgroup absent example
hosts: ipaserver
become: true
tasks:
- name: Ensure hostgroup automember rule ipaservers is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
name: ipaservers
automember_type: hostgroup
state: absent
ansible-freeipa-master/playbooks/automember/automember-hostgroup-membership-all-hosts-rebuilt.yml 0000664 0000000 0000000 00000000456 14600563364 0034170 0 ustar 00root root 0000000 0000000 ---
- name: Automember hostgroup membership for all hosts rebuilt example
hosts: ipaserver
become: true
tasks:
- name: Ensure hostgroup membership for all hosts has been rebuilt
ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: hostgroup
state: rebuilt
ansible-freeipa-master/playbooks/automember/automember-hostgroup-membership-hosts-rebuilt.yml 0000664 0000000 0000000 00000000524 14600563364 0033416 0 ustar 00root root 0000000 0000000 ---
- name: Automember hostgroup membership for given hosts rebuilt example
hosts: ipaserver
become: true
tasks:
- name: Ensure hostgroup membership for given hosts has been rebuilt
ipaautomember:
ipaadmin_password: SomeADMINpassword
hosts:
- host1.mydomain.com
- host2.mydomain.com
state: rebuilt
ansible-freeipa-master/playbooks/automember/automember-hostgroup-orphans-removed.yml 0000664 0000000 0000000 00000000435 14600563364 0031573 0 ustar 00root root 0000000 0000000 ---
- name: Automember orphan hostgroup rules are removed example
hosts: ipaserver
become: true
tasks:
- name: Ensure orphan hostgroup rules are removed
ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: hostgroup
state: orphans_removed
ansible-freeipa-master/playbooks/automember/automember-hostgroup-present.yml 0000664 0000000 0000000 00000000447 14600563364 0030145 0 ustar 00root root 0000000 0000000 ---
- name: Automember hostgroup present example
hosts: ipaserver
become: true
tasks:
- name: Ensure hostgroup automember rule ipaservers is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
name: ipaservers
automember_type: hostgroup
state: present
ansible-freeipa-master/playbooks/automember/automember-hostgroup-rule-absent.yml 0000664 0000000 0000000 00000000624 14600563364 0030703 0 ustar 00root root 0000000 0000000 ---
- name: Automember hostgroup rule member absent example
hosts: ipaserver
become: true
tasks:
- name: Ensure hostgroup automember condition is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
name: "My domain hosts"
automember_type: hostgroup
state: absent
action: member
inclusive:
- key: fqdn
expression: ".*.mydomain.com"
ansible-freeipa-master/playbooks/automember/automember-hostgroup-rule-present.yml 0000664 0000000 0000000 00000000627 14600563364 0031112 0 ustar 00root root 0000000 0000000 ---
- name: Automember hostgroup rule member present example
hosts: ipaserver
become: true
tasks:
- name: Ensure hostgroup automember condition is present
ipaautomember:
ipaadmin_password: SomeADMINpassword
name: "My domain hosts"
automember_type: hostgroup
state: present
action: member
inclusive:
- key: fqdn
expression: ".*.mydomain.com"
ansible-freeipa-master/playbooks/automount/ 0000775 0000000 0000000 00000000000 14600563364 0021442 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/automount/automount-location-absent.yml 0000664 0000000 0000000 00000000441 14600563364 0027277 0 ustar 00root root 0000000 0000000 ---
- name: Automount locations absnet example
hosts: ipaserver
become: true
tasks:
- name: Ensure automount locations DMZ and internal are absent
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name:
- DMZ
- internal
state: absent
ansible-freeipa-master/playbooks/automount/automount-location-present.yml 0000664 0000000 0000000 00000000443 14600563364 0027505 0 ustar 00root root 0000000 0000000 ---
- name: Automount location present example
hosts: ipaserver
become: true
tasks:
- name: Ensure automount locations DMZ and internal are present
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name:
- DMZ
- internal
state: present
ansible-freeipa-master/playbooks/automount/automount-map-absent.yml 0000664 0000000 0000000 00000000377 14600563364 0026254 0 ustar 00root root 0000000 0000000 ---
- name: Automount map absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure map TestMap is absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
state: absent
ansible-freeipa-master/playbooks/automount/automount-map-indirect-map.yml 0000664 0000000 0000000 00000000471 14600563364 0027347 0 ustar 00root root 0000000 0000000 ---
- name: Managed automount maps
hosts: ipaserver
become: false
gather_facts: false
tasks:
- name: Playbook to add an indirect automount map
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: auto.indirect
location: DMZ
parent: auto.DMZ
mount: dmz_indirect
ansible-freeipa-master/playbooks/automount/automount-map-present.yml 0000664 0000000 0000000 00000000416 14600563364 0026452 0 ustar 00root root 0000000 0000000 ---
- name: Automount map present example
hosts: ipaserver
become: no
tasks:
- name: Ensure map TestMap is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
desc: "this is a test map"
ansible-freeipa-master/playbooks/automount/automountkey-present.yml 0000664 0000000 0000000 00000000464 14600563364 0026413 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage an automout key
hosts: ipaserver
tasks:
- name: Ensure autmount key is present
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
mapname: TestMap
key: TestKey
info: 192.168.122.1:/exports
state: present
ansible-freeipa-master/playbooks/automount/automountkey-renamed.yml 0000664 0000000 0000000 00000000536 14600563364 0026346 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage an automount key
hosts: ipaserver
tasks:
- name: Ensure aumount key TestKey is renamed to NewKeyName
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
automountlocationcn: TestLocation
automountmapname: TestMap
automountkey: TestKey
newname: NewKeyName
state: renamed
ansible-freeipa-master/playbooks/automount/automoutkey-absent.yml 0000664 0000000 0000000 00000000421 14600563364 0026022 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage an automount key
hosts: ipaserver
tasks:
- name: Ensure autmount key is present
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
mapname: TestMap
key: TestKey
state: absent
ansible-freeipa-master/playbooks/backup-server-to-controller.yml 0000664 0000000 0000000 00000000331 14600563364 0025501 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to backup IPA server to controller
hosts: ipaserver
become: true
vars:
ipabackup_to_controller: yes
# ipabackup_keep_on_server: yes
roles:
- role: ipabackup
state: present
ansible-freeipa-master/playbooks/backup-server.yml 0000664 0000000 0000000 00000000175 14600563364 0022706 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to backup IPA server
hosts: ipaserver
become: true
roles:
- role: ipabackup
state: present
ansible-freeipa-master/playbooks/cert/ 0000775 0000000 0000000 00000000000 14600563364 0020344 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/cert/cert-hold.yml 0000664 0000000 0000000 00000000465 14600563364 0022755 0 ustar 00root root 0000000 0000000 ---
- name: Certificate manage example
hosts: ipaserver
become: false
gather_facts: false
module_defaults:
ipacert:
ipaadmin_password: SomeADMINpassword
ipaapi_context: client
tasks:
- name: Temporarily hold a certificate
ipacert:
serial_number: 12345
state: held
ansible-freeipa-master/playbooks/cert/cert-release.yml 0000664 0000000 0000000 00000000465 14600563364 0023447 0 ustar 00root root 0000000 0000000 ---
- name: Certificate manage example
hosts: ipaserver
become: false
gather_facts: false
module_defaults:
ipacert:
ipaadmin_password: SomeADMINpassword
ipaapi_context: client
tasks:
- name: Release a certificate hold
ipacert:
serial_number: 12345
state: released
ansible-freeipa-master/playbooks/cert/cert-request-host.yml 0000664 0000000 0000000 00000001707 14600563364 0024472 0 ustar 00root root 0000000 0000000 ---
- name: Certificate manage example
hosts: ipaserver
become: false
gather_facts: false
module_defaults:
ipacert:
ipaadmin_password: SomeADMINpassword
ipaapi_context: client
tasks:
- name: Request a certificate for a host
ipacert:
csr: |
-----BEGIN CERTIFICATE REQUEST-----
MIIBWjCBxAIBADAbMRkwFwYDVQQDDBBob3N0LmV4YW1wbGUuY29tMIGfMA0GCSqG
SIb3DQEBAQUAA4GNADCBiQKBgQCzR3Vd4Cwl0uVgwB3+wxz+4JldFk3x526bPeuK
g8EEc+rEHILzJWeXC8ywCYPOgK9n7hrdMfVQiIx3yHYrY+0IYuLehWow4o1iJEf5
urPNAP9K9C4Y7MMXzzoQmoWR3IFQQpOYwvWOtiZfvrhmtflnYEGLE2tgz53gOQHD
NnbCCwIDAQABoAAwDQYJKoZIhvcNAQELBQADgYEAgF+6YC39WhnvmFgNz7pjAh5E
2ea3CgG+zrzAyiSBGG6WpXEjqMRnAQxciQNGxQacxjwWrscZidZzqg8URJPugewq
tslYB1+RkZn+9UWtfnWvz89+xnOgco7JlytnbH10Nfxt5fXXx13rY0tl54jBtk2W
422eYZ12wb4gjNcQy3A=
-----END CERTIFICATE REQUEST-----
principal: host/host.example.com
state: requested
ansible-freeipa-master/playbooks/cert/cert-request-service.yml 0000664 0000000 0000000 00000001261 14600563364 0025150 0 ustar 00root root 0000000 0000000 ---
- name: Certificate manage example
hosts: ipaserver
become: false
gather_facts: false
module_defaults:
ipacert:
ipaadmin_password: SomeADMINpassword
ipaapi_context: client
tasks:
- name: Request a certificate for a service
ipacert:
csr: |
-----BEGIN CERTIFICATE REQUEST-----
MIGYMEwCAQAwGTEXMBUGA1UEAwwOZnJlZWlwYSBydWxlcyEwKjAFBgMrZXADIQBs
HlqIr4b/XNK+K8QLJKIzfvuNK0buBhLz3LAzY7QDEqAAMAUGAytlcANBAF4oSCbA
5aIPukCidnZJdr491G4LBE+URecYXsPknwYb+V+ONnf5ycZHyaFv+jkUBFGFeDgU
SYaXm/gF8cDYjQI=
-----END CERTIFICATE REQUEST-----
principal: HTTP/www.example.com
add: true
state: requested
ansible-freeipa-master/playbooks/cert/cert-request-user.yml 0000664 0000000 0000000 00000002027 14600563364 0024467 0 ustar 00root root 0000000 0000000 ---
- name: Certificate manage example
hosts: ipaserver
become: false
gather_facts: false
module_defaults:
ipacert:
ipaadmin_password: SomeADMINpassword
ipaapi_context: client
tasks:
- name: Request a certificate for a user with a specific profile
ipacert:
csr: |
-----BEGIN CERTIFICATE REQUEST-----
MIIBejCB5AIBADAQMQ4wDAYDVQQDDAVwaW5reTCBnzANBgkqhkiG9w0BAQEFAAOB
jQAwgYkCgYEA7uChccy1Is1FTM0SF23WPYW472E3ozeLh2kzhKR9Ni6FLmeEGgu7
/hicR1VwvXHYkNwI1tpW9LqxRVvgr6vheqHySljrBcoRfshfYvKejp03l2327Bfq
BNxXqLcHylNEyg8SH0u63bWyxtgoDBfdZwdGAhYuJ+g4ev79J5eYoB0CAwEAAaAr
MCkGCSqGSIb3DQEJDjEcMBowGAYHKoZIzlYIAQQNDAtoZWxsbyB3b3JsZDANBgkq
hkiG9w0BAQsFAAOBgQADCi5BHDv1mrBFDWqYytFpQ1mrvr/mdax3AYXxNL2UEV8j
AqZAFTEnJXL/u1eVQtI1yotqxakyUBN4XZBP2CBgJRO93Mtry8cgvU1sPdU8Mavx
5gSnlP74Hio2ziscWWydlxpYxFx0gkKvu+0nyIpz954SVYwQ2wwk5FRqZnxI5w==
-----END CERTIFICATE REQUEST-----
principal: pinky
profile: IECUserRoles
state: requested
ansible-freeipa-master/playbooks/cert/cert-retrieve.yml 0000664 0000000 0000000 00000000517 14600563364 0023652 0 ustar 00root root 0000000 0000000 ---
- name: Certificate manage example
hosts: ipaserver
become: false
gather_facts: false
module_defaults:
ipacert:
ipaadmin_password: SomeADMINpassword
ipaapi_context: client
tasks:
- name: Retrieve a certificate
ipacert:
serial_number: 12345
state: retrieved
register: cert_retrieved
ansible-freeipa-master/playbooks/cert/cert-revoke.yml 0000664 0000000 0000000 00000000634 14600563364 0023320 0 ustar 00root root 0000000 0000000 ---
- name: Certificate manage example
hosts: ipaserver
become: false
gather_facts: false
module_defaults:
ipacert:
ipaadmin_password: SomeADMINpassword
ipaapi_context: client
tasks:
- name: Permanently revoke a certificate issued by a lightweight sub-CA
ipacert:
serial_number: 12345
ca: vpn-ca
# reason: keyCompromise (1)
reason: 1
state: revoked
ansible-freeipa-master/playbooks/config/ 0000775 0000000 0000000 00000000000 14600563364 0020654 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/config/change-ipa-domain-netbios-name.yml 0000664 0000000 0000000 00000000417 14600563364 0027221 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to change IPA domain netbios name
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Set IPA domain netbios name
ipaconfig:
ipaadmin_password: SomeADMINpassword
enable_sid: yes
netbios_name: IPADOM
ansible-freeipa-master/playbooks/config/generate-users-groups-sids.yml 0000664 0000000 0000000 00000000462 14600563364 0026607 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure SIDs are enabled and users and groups have SIDs
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Enable SID and generate users and groups SIDS
ipaconfig:
ipaadmin_password: SomeADMINpassword
enable_sid: yes
add_sids: yes
ansible-freeipa-master/playbooks/config/retrieve-config.yml 0000664 0000000 0000000 00000000530 14600563364 0024465 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle global IPA configuration
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Query IPA global configuration
ipaconfig:
ipaadmin_password: SomeADMINpassword
register: serverconfig
- name: Display current configuration.
ansible.builtin.debug:
msg: "{{ serverconfig }}"
ansible-freeipa-master/playbooks/config/set-ca-renewal-master-server.yml 0000664 0000000 0000000 00000000414 14600563364 0027002 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle global IPA configuration
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Set ca_renewal_master_server
ipaconfig:
ipaadmin_password: SomeADMINpassword
ca_renewal_master_server: carenewal.example.com
ansible-freeipa-master/playbooks/copy-all-backups-from-server.yml 0000664 0000000 0000000 00000000315 14600563364 0025544 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to copy all backups from IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name: all
ipabackup_to_controller: yes
roles:
- role: ipabackup
state: copied
ansible-freeipa-master/playbooks/copy-backup-from-controller.yml 0000664 0000000 0000000 00000000414 14600563364 0025470 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to copy a backup from controller to the IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name: ipaserver.test.local_ipa-full-2020-10-22-11-11-44
ipabackup_from_controller: yes
roles:
- role: ipabackup
state: copied
ansible-freeipa-master/playbooks/copy-backup-from-server.yml 0000664 0000000 0000000 00000000341 14600563364 0024612 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to copy backup from IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name: ipa-full-2020-10-22-11-11-44
ipabackup_to_controller: yes
roles:
- role: ipabackup
state: copied
ansible-freeipa-master/playbooks/delegation/ 0000775 0000000 0000000 00000000000 14600563364 0021522 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/delegation/delegation-absent.yml 0000664 0000000 0000000 00000000404 14600563364 0025630 0 ustar 00root root 0000000 0000000 ---
- name: Delegation absent
hosts: ipaserver
become: true
tasks:
- name: Ensure delegation "basic manager attributes" is absent
ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
state: absent
ansible-freeipa-master/playbooks/delegation/delegation-member-absent.yml 0000664 0000000 0000000 00000000620 14600563364 0027075 0 ustar 00root root 0000000 0000000 ---
- name: Delegation member absent
hosts: ipaserver
become: true
tasks:
- name: Ensure delegation "basic manager attributes" member attributes employeenumber and employeetype are absent
ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- employeenumber
- employeetype
action: member
state: absent
ansible-freeipa-master/playbooks/delegation/delegation-member-present.yml 0000664 0000000 0000000 00000000532 14600563364 0027303 0 ustar 00root root 0000000 0000000 ---
- name: Delegation member present
hosts: ipaserver
become: true
tasks:
- name: Ensure delegation "basic manager attributes" member attribute departmentnumber is present
ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- departmentnumber
action: member
ansible-freeipa-master/playbooks/delegation/delegation-present.yml 0000664 0000000 0000000 00000000546 14600563364 0026043 0 ustar 00root root 0000000 0000000 ---
- name: Delegation present
hosts: ipaserver
become: true
tasks:
- name: Ensure delegation "basic manager attributes" is present
ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
group: managers
membergroup: employees
ansible-freeipa-master/playbooks/dnsconfig/ 0000775 0000000 0000000 00000000000 14600563364 0021361 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/dnsconfig/disable-global-forwarders.yml 0000664 0000000 0000000 00000000337 14600563364 0027124 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to disable global DNS forwarders
hosts: ipaserver
become: true
tasks:
- name: Disable global forwarders.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
forward_policy: none
ansible-freeipa-master/playbooks/dnsconfig/disallow-reverse-sync.yml 0000664 0000000 0000000 00000000366 14600563364 0026352 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to disallow reverse record synchronization.
hosts: ipaserver
become: true
tasks:
- name: Disallow reverse record synchronization.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
allow_sync_ptr: no
ansible-freeipa-master/playbooks/dnsconfig/forwarders-absent.yml 0000664 0000000 0000000 00000000534 14600563364 0025536 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle global DNS configuration
hosts: ipaserver
become: true
tasks:
- name: Set dnsconfig forwarders.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
forwarders:
- ip_address: 8.8.4.4
- ip_address: 2001:4860:4860::8888
port: 53
action: member
state: absent
ansible-freeipa-master/playbooks/dnsconfig/forwarders-present.yml 0000664 0000000 0000000 00000000510 14600563364 0025734 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle global DNS configuration
hosts: ipaserver
become: true
tasks:
- name: Set dnsconfig forwarders.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
forwarders:
- ip_address: 8.8.4.4
- ip_address: 2001:4860:4860::8888
port: 53
action: member
ansible-freeipa-master/playbooks/dnsconfig/set-configuration.yml 0000664 0000000 0000000 00000000535 14600563364 0025547 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle global DNS configuration
hosts: ipaserver
become: true
tasks:
- name: Set dnsconfig.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
forwarders:
- ip_address: 8.8.4.4
- ip_address: 2001:4860:4860::8888
port: 53
forward_policy: only
allow_sync_ptr: yes
ansible-freeipa-master/playbooks/dnsforwardzone/ 0000775 0000000 0000000 00000000000 14600563364 0022454 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/dnsforwardzone/ensure-dnsforwardzone-is-absent.yml 0000664 0000000 0000000 00000000364 14600563364 0031431 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS forward zone
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure DNS forward zone is absent
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
state: absent
ansible-freeipa-master/playbooks/dnsforwardzone/ensure-dnsforwardzone-is-present.yml 0000664 0000000 0000000 00000000571 14600563364 0031635 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS forward zone
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure DNS forward zone is present
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
name: example.com
forwarders:
- ip_address: 8.8.8.8
forwardpolicy: first
skip_overlap_check: true
permission: yes
ansible-freeipa-master/playbooks/dnsforwardzone/ensure-dnsforwardzone-with-forwarder-port.yml 0000664 0000000 0000000 00000000564 14600563364 0033474 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS forward zone
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure DNS forward zone is present with forwarder address and non-standard port.
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
name: example.com
forwarders:
- ip_address: 192.168.100.123
port: 8063
ansible-freeipa-master/playbooks/dnsrecord/ 0000775 0000000 0000000 00000000000 14600563364 0021372 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/dnsrecord/ensure-A-and-AAAA-records-are-absent.yml 0000664 0000000 0000000 00000000630 14600563364 0030472 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure that 'host04' A and AAAA records are absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: ipatest.local
records:
- name: host04
a_ip_address: 192.168.122.104
- name: host04
aaaa_ip_address: ::1
state: absent
ansible-freeipa-master/playbooks/dnsrecord/ensure-A-and-AAAA-records-are-present.yml 0000664 0000000 0000000 00000000605 14600563364 0030700 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure that 'host04' A and AAAA records are present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: ipatest.local
records:
- name: host04
a_ip_address: 192.168.122.104
- name: host04
aaaa_ip_address: ::1
ansible-freeipa-master/playbooks/dnsrecord/ensure-CNAME-record-is-absent.yml 0000664 0000000 0000000 00000000541 14600563364 0027376 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure that 'host04' has CNAME, with cname_hostname, is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
name: host04
cname_hostname: host04.example.com
state: absent
ansible-freeipa-master/playbooks/dnsrecord/ensure-CNAME-record-is-present.yml 0000664 0000000 0000000 00000000516 14600563364 0027604 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure that 'host04' has CNAME, with cname_hostname, is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
name: host04
cname_hostname: host04.example.com
ansible-freeipa-master/playbooks/dnsrecord/ensure-MX-record-is-present.yml 0000664 0000000 0000000 00000000535 14600563364 0027306 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure an MX record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: '@'
record_type: 'MX'
record_value: '1 mailserver.example.com'
zone_name: example.com
state: present
ansible-freeipa-master/playbooks/dnsrecord/ensure-PTR-record-is-present.yml 0000664 0000000 0000000 00000000547 14600563364 0027432 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure a PTR record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: 5
record_type: 'PTR'
record_value: 'internal.ipa.example.com'
zone_name: 2.168.192.in-addr.arpa
state: present
ansible-freeipa-master/playbooks/dnsrecord/ensure-SRV-record-is-present.yml 0000664 0000000 0000000 00000000565 14600563364 0027437 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure a SRV record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: _kerberos._udp.example.com
record_type: 'SRV'
record_value: '10 50 88 ipa.example.com'
zone_name: example.com
state: present
ansible-freeipa-master/playbooks/dnsrecord/ensure-SSHFP-record-is-present.yml 0000664 0000000 0000000 00000000703 14600563364 0027642 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
# SSHFP fingerprint generated with `ssh-keygen -r host04.testzone.local`
- name: Ensure a SSHFP record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
name: host04
sshfp_algorithm: 1
sshfp_fp_type: 1
sshfp_fingerprint: d21802c61733e055b8d16296cbce300efb8a167a
ansible-freeipa-master/playbooks/dnsrecord/ensure-TLSA-record-is-present.yml 0000664 0000000 0000000 00000000664 14600563364 0027530 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure a TLSA record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: example.com
name: host04
tlsa_cert_usage: 3
tlsa_selector: 1
tlsa_matching_type: 1
tlsa_cert_association_data: 9c0ad776dbeae8d9d55b0ad42899d30235c114d5f918fd69746e4279e47bdaa2
ansible-freeipa-master/playbooks/dnsrecord/ensure-TXT-record-is-present.yml 0000664 0000000 0000000 00000000527 14600563364 0027442 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure a TXT record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: _kerberos
record_type: 'TXT'
record_value: 'EXAMPLE.COM'
zone_name: example.com
state: present
ansible-freeipa-master/playbooks/dnsrecord/ensure-URI-record-is-present.yml 0000664 0000000 0000000 00000000617 14600563364 0027422 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure a URI record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: _ftp._tcp
record_type: 'URI'
uri_priority: 10
uri_weight: 1
uri_target: ftp://ftp.example.com/public
zone_name: example.com
state: present
ansible-freeipa-master/playbooks/dnsrecord/ensure-dnsrecord-is-absent.yml 0000664 0000000 0000000 00000000535 14600563364 0027265 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure that dns localhost AAAA record is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: example.com
record_type: 'AAAA'
record_value: '::1'
state: absent
ansible-freeipa-master/playbooks/dnsrecord/ensure-dnsrecord-is-present.yml 0000664 0000000 0000000 00000000520 14600563364 0027463 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure that dns record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: example.com
record_type: 'AAAA'
record_value: '::1'
state: present
ansible-freeipa-master/playbooks/dnsrecord/ensure-dnsrecord-with-reverse-is-present.yml 0000664 0000000 0000000 00000000527 14600563364 0032114 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure that dns record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: example.com
ip_address: 192.160.123.45
create_reverse: yes
state: present
ansible-freeipa-master/playbooks/dnsrecord/ensure-multiple-A-records-are-present.yml 0000664 0000000 0000000 00000000605 14600563364 0031310 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure that 'host04' has multiple A records.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: ipatest.local
name: host01
a_rec:
- 192.168.122.221
- 192.168.122.222
- 192.168.122.223
- 192.168.122.224
ansible-freeipa-master/playbooks/dnsrecord/ensure-presence-multiple-records.yml 0000664 0000000 0000000 00000001011 14600563364 0030501 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage DNS records.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure that multiple dns records are present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
records:
- name: host01
zone_name: example.com
record_type: A
record_value:
- 192.168.122.112
- 192.168.122.122
- name: host01
zone_name: testzone.local
record_type: AAAA
record_value: ::1
ansible-freeipa-master/playbooks/dnszone/ 0000775 0000000 0000000 00000000000 14600563364 0021067 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/dnszone/disable-zone-forwarders.yml 0000664 0000000 0000000 00000000364 14600563364 0026345 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to disable DNS zone forwarders
hosts: ipaserver
become: true
tasks:
- name: Disable zone forwarders.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
forward_policy: none
ansible-freeipa-master/playbooks/dnszone/dnszone-absent.yml 0000664 0000000 0000000 00000000337 14600563364 0024547 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure DNS zone is absent
hosts: ipaserver
become: true
tasks:
- name: Remove zone.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
state: absent
ansible-freeipa-master/playbooks/dnszone/dnszone-all-params.yml 0000664 0000000 0000000 00000001504 14600563364 0025321 0 ustar 00root root 0000000 0000000 ---
- name: All dnszone parameters
hosts: ipaserver
become: true
tasks:
- name: Ensure zone is present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_sync_ptr: true
dynamic_update: true
dnssec: true
allow_transfer:
- 1.1.1.1
- 2.2.2.2
allow_query:
- 1.1.1.1
- 2.2.2.2
forwarders:
- ip_address: 8.8.8.8
- ip_address: 8.8.4.4
port: 52
#serial: 1234
refresh: 3600
retry: 900
expire: 1209600
minimum: 3600
ttl: 60
default_ttl: 90
name_server: ipaserver.test.local.
admin_email: admin.admin@example.com
nsec3param_rec: "1 7 100 0123456789abcdef"
skip_overlap_check: true
skip_nameserver_check: true
state: present
ansible-freeipa-master/playbooks/dnszone/dnszone-disable.yml 0000664 0000000 0000000 00000000331 14600563364 0024670 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to disable DNS zone
hosts: ipaserver
become: true
tasks:
- name: Disable zone.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
state: disabled
ansible-freeipa-master/playbooks/dnszone/dnszone-enable.yml 0000664 0000000 0000000 00000000326 14600563364 0024517 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to enable DNS zone
hosts: ipaserver
become: true
tasks:
- name: Enable zone.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
state: enabled
ansible-freeipa-master/playbooks/dnszone/dnszone-present.yml 0000664 0000000 0000000 00000000325 14600563364 0024750 0 ustar 00root root 0000000 0000000 ---
- name: Dnszone present
hosts: ipaserver
become: true
tasks:
- name: Ensure zone is present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
state: present
ansible-freeipa-master/playbooks/dnszone/dnszone-reverse-from-ip.yml 0000664 0000000 0000000 00000000614 14600563364 0026313 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure DNS zone exist
hosts: ipaserver
become: true
tasks:
- name: Ensure zone exist, finding zone name from IP address.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 10.1.2.3/24
register: result
- name: Zone name inferred from `name_from_ip`
ansible.builtin.debug:
msg: "Zone created: {{ result.dnszone.name }}"
ansible-freeipa-master/playbooks/group/ 0000775 0000000 0000000 00000000000 14600563364 0020543 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/group/add-group.yml 0000664 0000000 0000000 00000000712 14600563364 0023150 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
- name: Create group ops with gid 1234
ipagroup:
ipaadmin_password: SomeADMINpassword
name: ops
gidnumber: 1234
- name: Create group sysops
ipagroup:
ipaadmin_password: SomeADMINpassword
name: sysops
user:
- pinky
- name: Create group appops
ipagroup:
ipaadmin_password: SomeADMINpassword
name: appops
ansible-freeipa-master/playbooks/group/add-groups-to-group.yml 0000664 0000000 0000000 00000000404 14600563364 0025103 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
- name: Add group members sysops and appops to group sysops
ipagroup:
ipaadmin_password: SomeADMINpassword
name: ops
group:
- sysops
- appops
ansible-freeipa-master/playbooks/group/add-groups.yml 0000664 0000000 0000000 00000001320 14600563364 0023327 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle multiple groups
hosts: ipaserver
tasks:
- name: Create multiple groups ops, sysops
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: ops
gidnumber: 1234
- name: sysops
- name: Add user and group members to groups sysops and appops
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: sysops
user:
- user1
- name: appops
group:
- group2
- name: Create multiple non-POSIX and external groups
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: nongroup
nonposix: true
- name: extgroup
external: true
ansible-freeipa-master/playbooks/group/add-user-to-group.yml 0000664 0000000 0000000 00000000375 14600563364 0024551 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
- name: Add user member brain to group sysops
ipagroup:
ipaadmin_password: SomeADMINpassword
name: sysops
action: member
user:
- brain
ansible-freeipa-master/playbooks/group/delete-group.yml 0000664 0000000 0000000 00000000353 14600563364 0023663 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
- name: Remove goups sysops, appops and ops
ipagroup:
ipaadmin_password: SomeADMINpassword
name: sysops,appops,ops
state: absent
ansible-freeipa-master/playbooks/hbacrule/ 0000775 0000000 0000000 00000000000 14600563364 0021174 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/hbacrule/ensure-hbarule-allhosts-absent.yml 0000664 0000000 0000000 00000000347 14600563364 0027745 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Rule allhosts is absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allhosts
state: absent
ansible-freeipa-master/playbooks/hbacrule/ensure-hbarule-allhosts-disabled.yml 0000664 0000000 0000000 00000000353 14600563364 0030235 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Rule allhosts is disabled
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allhosts
state: disabled
ansible-freeipa-master/playbooks/hbacrule/ensure-hbarule-allhosts-enabled.yml 0000664 0000000 0000000 00000000351 14600563364 0030056 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Rule allhosts is enabled
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allhosts
state: enabled
ansible-freeipa-master/playbooks/hbacrule/ensure-hbarule-allhosts-present.yml 0000664 0000000 0000000 00000000354 14600563364 0030147 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Rule allhosts is present
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allhosts
usercategory: all
ansible-freeipa-master/playbooks/hbacrule/ensure-hbarule-allhosts-server-member-absent.yml 0000664 0000000 0000000 00000000436 14600563364 0032515 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure host server is absent in HBAC Rule allhosts
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allhosts
host: server
action: member
state: absent
ansible-freeipa-master/playbooks/hbacrule/ensure-hbarule-allhosts-server-member-present.yml 0000664 0000000 0000000 00000000413 14600563364 0032714 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure host server is present in HBAC Rule allhosts
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allhosts
host: server
action: member
ansible-freeipa-master/playbooks/hbacsvc/ 0000775 0000000 0000000 00000000000 14600563364 0021020 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/hbacsvc/ensure-hbacsvc-absent.yml 0000664 0000000 0000000 00000000365 14600563364 0025731 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Services for http and tftp are absent
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
name: http,tftp
state: absent
ansible-freeipa-master/playbooks/hbacsvc/ensure-hbacsvc-present.yml 0000664 0000000 0000000 00000000620 14600563364 0026127 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Service for http is present
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
name: http
description: Web service
- name: Ensure HBAC Service for tftp is present
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
name: tftp
description: TFTP service
ansible-freeipa-master/playbooks/hbacsvcgroup/ 0000775 0000000 0000000 00000000000 14600563364 0022075 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/hbacsvcgroup/ensure-hbacsvcgroup-absent.yml 0000664 0000000 0000000 00000000412 14600563364 0030054 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Service Group login is absent
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: login
hbacsvc:
- sshd
state: absent
ansible-freeipa-master/playbooks/hbacsvcgroup/ensure-hbacsvcgroup-member-absent.yml 0000664 0000000 0000000 00000000465 14600563364 0031331 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Services sshd is absent in HBAC Service Group login
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: login
hbacsvc:
- sshd
action: member
state: absent
ansible-freeipa-master/playbooks/hbacsvcgroup/ensure-hbacsvcgroup-member-present.yml 0000664 0000000 0000000 00000000441 14600563364 0031527 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Service sshd is present in HBAC Service Group login
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: login
hbacsvc:
- sshd
action: member
ansible-freeipa-master/playbooks/hbacsvcgroup/ensure-hbacsvcgroup-present.yml 0000664 0000000 0000000 00000000441 14600563364 0030262 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Service sshd is present in HBAC Service Group login
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: login
hbacsvc:
- sshd
action: member
ansible-freeipa-master/playbooks/host/ 0000775 0000000 0000000 00000000000 14600563364 0020364 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/host/add-host.yml 0000777 0000000 0000000 00000000000 14600563364 0025763 2host-present.yml ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/host/delete-host.yml 0000664 0000000 0000000 00000000357 14600563364 0023331 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
- name: Ensure host host01.example.com is absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
state: absent
ansible-freeipa-master/playbooks/host/disable-host.yml 0000664 0000000 0000000 00000000350 14600563364 0023463 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
- name: Disable host host01.example.com
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
state: disabled
ansible-freeipa-master/playbooks/host/ensure_host_with_randompassword.yml 0000664 0000000 0000000 00000000730 14600563364 0027623 0 ustar 00root root 0000000 0000000 ---
- name: Ensure host with random password
hosts: ipaserver
become: true
tasks:
- name: Host "{{ 'host1.' + ipaserver_domain }}" present with random password
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ 'host1.' + ipaserver_domain }}"
random: yes
force: yes
update_password: on_create
register: ipahost
- name: Print generated random password
ansible.builtin.debug:
var: ipahost.host.randompassword
ansible-freeipa-master/playbooks/host/host-member-allow_create_keytab-absent.yml 0000664 0000000 0000000 00000001155 14600563364 0030603 0 ustar 00root root 0000000 0000000 ---
- name: Host member allow_create_keytab absent
hosts: ipaserver
become: true
tasks:
- name: Host host1.example.com members allow_create_keytab absent for users, groups, hosts and hostgroups
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- host02.example.com
- host03.example.com
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
ansible-freeipa-master/playbooks/host/host-member-allow_create_keytab-present.yml 0000664 0000000 0000000 00000001133 14600563364 0031003 0 ustar 00root root 0000000 0000000 ---
- name: Host member allow_create_keytab present
hosts: ipaserver
become: true
tasks:
- name: Host host1.example.com members allow_create_keytab present for users, groups, hosts and hostgroups
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- host02.example.com
- host03.example.com
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
ansible-freeipa-master/playbooks/host/host-member-allow_retrieve_keytab-absent.yml 0000664 0000000 0000000 00000001171 14600563364 0031163 0 ustar 00root root 0000000 0000000 ---
- name: Host member allow_retrieve_keytab absent
hosts: ipaserver
become: true
tasks:
- name: Host host1.example.com members allow_retrieve_keytab absent for users, groups, hosts and hostgroups
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- host02.example.com
- host03.example.com
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
ansible-freeipa-master/playbooks/host/host-member-allow_retrieve_keytab-present.yml 0000664 0000000 0000000 00000001147 14600563364 0031372 0 ustar 00root root 0000000 0000000 ---
- name: Host member allow_retrieve_keytab present
hosts: ipaserver
become: true
tasks:
- name: Host host1.example.com members allow_retrieve_keytab present for users, groups, hosts and hostgroups
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- host02.example.com
- host03.example.com
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
ansible-freeipa-master/playbooks/host/host-member-certificate-absent.yml 0000664 0000000 0000000 00000002726 14600563364 0027072 0 ustar 00root root 0000000 0000000 ---
- name: Host member certificate absent
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com member certificate absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
certificate:
- >
MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvc
NAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMD
EwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBA
QUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6X
sqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7G
PHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8H
nSVLF6Ys9+cJMJ7HuwOI+wYt3gkmspsir1tccmf4x1PP+yHJWdcXyetlFRc
mZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2Q
glidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplR
BoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldn
f13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBA
f8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4K
k+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGs
GLv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31y
kBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0
fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9m
BDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8
AN65NAdv7+js8jKUKCuyji8r3
action: member
state: absent
ansible-freeipa-master/playbooks/host/host-member-certificate-present.yml 0000664 0000000 0000000 00000002704 14600563364 0027272 0 ustar 00root root 0000000 0000000 ---
- name: Host member certificate present
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com member certificate present
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
certificate:
- >
MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvc
NAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMD
EwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBA
QUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6X
sqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7G
PHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8H
nSVLF6Ys9+cJMJ7HuwOI+wYt3gkmspsir1tccmf4x1PP+yHJWdcXyetlFRc
mZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2Q
glidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplR
BoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldn
f13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBA
f8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4K
k+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGs
GLv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31y
kBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0
fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9m
BDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8
AN65NAdv7+js8jKUKCuyji8r3
action: member
ansible-freeipa-master/playbooks/host/host-member-ipaddresses-absent.yml 0000664 0000000 0000000 00000000620 14600563364 0027105 0 ustar 00root root 0000000 0000000 ---
- name: Host member IP addresses absent
hosts: ipaserver
become: true
tasks:
- name: Ensure host01.example.com IP addresses absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
ip_address:
- 192.168.0.123
- fe80::20c:29ff:fe02:a1b3
- 192.168.0.124
- fe80::20c:29ff:fe02:a1b4
action: member
state: absent
ansible-freeipa-master/playbooks/host/host-member-ipaddresses-present.yml 0000664 0000000 0000000 00000000576 14600563364 0027323 0 ustar 00root root 0000000 0000000 ---
- name: Host member IP addresses present
hosts: ipaserver
become: true
tasks:
- name: Ensure host01.example.com IP addresses present
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
ip_address:
- 192.168.0.123
- fe80::20c:29ff:fe02:a1b3
- 192.168.0.124
- fe80::20c:29ff:fe02:a1b4
action: member
ansible-freeipa-master/playbooks/host/host-member-managedby_host-absent.yml 0000664 0000000 0000000 00000000516 14600563364 0027567 0 ustar 00root root 0000000 0000000 ---
- name: Host member managedby_host absent
hosts: ipaserver
become: true
tasks:
- name: Ensure host member managedby_host 'server.example.com' is absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
managedby_host: server.example.com
action: member
state: absent
ansible-freeipa-master/playbooks/host/host-member-managedby_host-present.yml 0000664 0000000 0000000 00000000474 14600563364 0027776 0 ustar 00root root 0000000 0000000 ---
- name: Host member managedby_host present
hosts: ipaserver
become: true
tasks:
- name: Ensure host member managedby_host 'server.example.com' is present
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
managedby_host: server.example.com
action: member
ansible-freeipa-master/playbooks/host/host-member-principal-absent.yml 0000664 0000000 0000000 00000000632 14600563364 0026563 0 ustar 00root root 0000000 0000000 ---
- name: Host member principal absent
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com principals host/testhost01.example.com and host/myhost01.example.com absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
principal:
- host/testhost01.example.com
- host/myhost01.example.com
action: member
state: absent
ansible-freeipa-master/playbooks/host/host-member-principal-present.yml 0000664 0000000 0000000 00000000610 14600563364 0026763 0 ustar 00root root 0000000 0000000 ---
- name: Host member principal present
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com principals host/testhost01.example.com and host/myhost01.example.com present
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
principal:
- host/testhost01.example.com
- host/myhost01.example.com
action: member
ansible-freeipa-master/playbooks/host/host-present-with-allow_create_keytab.yml 0000664 0000000 0000000 00000001141 14600563364 0030506 0 ustar 00root root 0000000 0000000 ---
- name: Host present with allow_create_keytab
hosts: ipaserver
become: true
tasks:
- name: Host host1.example.com present with allow_create_keytab for users, groups, hosts and hostgroups
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- host02.example.com
- host03.example.com
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
ip_address: 192.168.0.123
ansible-freeipa-master/playbooks/host/host-present-with-allow_retrieve_keytab.yml 0000664 0000000 0000000 00000001155 14600563364 0031075 0 ustar 00root root 0000000 0000000 ---
- name: Host present with allow_retrieve_keytab
hosts: ipaserver
become: true
tasks:
- name: Host host1.example.com present with allow_retrieve_keytab for users, groups, hosts and hostgroups
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- host02.example.com
- host03.example.com
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
ip_address: 192.168.0.123
ansible-freeipa-master/playbooks/host/host-present-with-certificate.yml 0000664 0000000 0000000 00000002674 14600563364 0027004 0 ustar 00root root 0000000 0000000 ---
- name: Host present with certificate
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com present with certificate
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
certificate:
- >
MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvc
NAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMD
EwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBA
QUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6X
sqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7G
PHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8H
nSVLF6Ys9+cJMJ7HuwOI+wYt3gkmspsir1tccmf4x1PP+yHJWdcXyetlFRc
mZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2Q
glidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplR
BoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldn
f13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBA
f8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4K
k+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGs
GLv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31y
kBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0
fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9m
BDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8
AN65NAdv7+js8jKUKCuyji8r3
force: yes
ansible-freeipa-master/playbooks/host/host-present-with-managedby_host.yml 0000664 0000000 0000000 00000000452 14600563364 0027476 0 ustar 00root root 0000000 0000000 ---
- name: Host present with managedby_host
hosts: ipaserver
become: true
tasks:
- name: Ensure host is present with managedby_host attribute.
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
managedby_host: server.example.com
force: yes
ansible-freeipa-master/playbooks/host/host-present-with-principal.yml 0000664 0000000 0000000 00000000607 14600563364 0026475 0 ustar 00root root 0000000 0000000 ---
- name: Host present with principal
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com present with principals host/testhost01.example.com and host/myhost01.example.com
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
principal:
- host/testhost01.example.com
- host/myhost01.example.com
force: yes
ansible-freeipa-master/playbooks/host/host-present-with-randompassword.yml 0000664 0000000 0000000 00000000626 14600563364 0027560 0 ustar 00root root 0000000 0000000 ---
- name: Host present with random password
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com present with random password
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
random: yes
force: yes
register: ipahost
- name: Print generated random password
ansible.builtin.debug:
var: ipahost.host.randompassword
ansible-freeipa-master/playbooks/host/host-present-with-several-ip-addresses.yml 0000664 0000000 0000000 00000001114 14600563364 0030530 0 ustar 00root root 0000000 0000000 ---
- name: Host present with several IP addresses
hosts: ipaserver
become: true
tasks:
- name: Ensure host is present
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
description: Example host
ip_address:
- 192.168.0.123
- fe80::20c:29ff:fe02:a1b3
- 192.168.0.124
- fe80::20c:29ff:fe02:a1b4
locality: Lab
ns_host_location: Lab
ns_os_version: CentOS 7
ns_hardware_platform: Lenovo T61
mac_address:
- "08:00:27:E3:B1:2D"
- "52:54:00:BD:97:1E"
state: present
ansible-freeipa-master/playbooks/host/host-present.yml 0000664 0000000 0000000 00000000722 14600563364 0023543 0 ustar 00root root 0000000 0000000 ---
- name: Host present
hosts: ipaserver
become: true
tasks:
- name: Ensure host is present
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
description: Example host
ip_address: 192.168.0.123
locality: Lab
ns_host_location: Lab
ns_os_version: CentOS 7
ns_hardware_platform: Lenovo T61
mac_address:
- "08:00:27:E3:B1:2D"
- "52:54:00:BD:97:1E"
state: present
ansible-freeipa-master/playbooks/host/hosts-member-certificate-absent.yml 0000664 0000000 0000000 00000005462 14600563364 0027255 0 ustar 00root root 0000000 0000000 ---
- name: Hosts member certificate absent
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.example.com and host01.example.com member certificate absent
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
certificate:
- >
MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvc
NAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMD
EwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBA
QUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6X
sqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7G
PHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8H
nSVLF6Ys9+cJMJ7HuwOI+wYt3gkmspsir1tccmf4x1PP+yHJWdcXyetlFRc
mZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2Q
glidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplR
BoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldn
f13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBA
f8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4K
k+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGs
GLv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31y
kBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0
fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9m
BDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8
AN65NAdv7+js8jKUKCuyji8r3
- name: host02.example.com
certificate:
- >
MIIC/zCCAeegAwIBAgIUAWE1vaA+mZd3nwZqwWH64EbHvR0wDQYJKoZIhvc
NAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4NDVaFw0yMD
EwMTMxNjI4NDVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBA
QUAA4IBDwAwggEKAoIBAQCWzJibKtN8Zf7LgandINhFonx99AKi44iaZkrl
MKEObE6Faf8NTUbUgK3VfJNYmCbA1baLVJ0YZJijJ7S/4o7h7eeqcJVXJkE
hWNTimWXNW/YCzTHe3SSapnSYOKmdHHRClplysL8OyyEG7pbX/aB9iAfFb/
+vUFCX5sMwFFrYxOimKJ9Pc/NRFtdv1wNw1rqWKF1ZzagWRlG4QgzRGwQ4q
uc7yO98TKikj2OPiIt7Zd46hbqQxmgGBtCkVOZIhxu77OmNrFsXmM4rZZpm
qh0UdqcpwkRojVnGXmNqeMCd6dNTnLhr9wukUYw0KgE57zCDVr9Ix+p/dA5
R1mG4RJ2XAgMBAAGjUzBRMB0GA1UdDgQWBBSbuiH2lNVrID3yt1SsFwtOFK
OnpTAfBgNVHSMEGDAWgBSbuiH2lNVrID3yt1SsFwtOFKOnpTAPBgNVHRMBA
f8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBCVWd293wWyohFqMFMHRBB
g97T2Uc1yeT0dMH4BpuOaCqQp4q5ep+uLcXEI6+3mEwm8pa/ULQCD8yLLdo
tIWlG3+h/4boFpdiPFcBDgT8kGe+0KOzB8Nt7E13QYOu12MNi10qwGrjKhd
hu1xBe4fpY5VCetVU1OLyuTsUyucQsFrtZI0SR83h+blbyoMZ7IhMngCfGU
e1bnYeWnLbpFbigKfPuVDWsMH2kgj05EAd5EgHkWbX8QA8hmcmDKfNT3YZM
8kiGQwmFrnQdq8bN0uHR8Nz+24cbmdbHcD65wlDW6GmYxi8mW+V6bAqn9pi
r/J14r4YFnqMGgjmdt81tscJV
action: member
state: absent
ansible-freeipa-master/playbooks/host/hosts-member-certificate-present.yml 0000664 0000000 0000000 00000005440 14600563364 0027455 0 ustar 00root root 0000000 0000000 ---
- name: Hosts member certificate present
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.example.com and host01.example.com member certificate present
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
certificate:
- >
MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvc
NAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMD
EwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBA
QUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6X
sqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7G
PHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8H
nSVLF6Ys9+cJMJ7HuwOI+wYt3gkmspsir1tccmf4x1PP+yHJWdcXyetlFRc
mZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2Q
glidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplR
BoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldn
f13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBA
f8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4K
k+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGs
GLv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31y
kBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0
fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9m
BDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8
AN65NAdv7+js8jKUKCuyji8r3
- name: host02.example.com
certificate:
- >
MIIC/zCCAeegAwIBAgIUAWE1vaA+mZd3nwZqwWH64EbHvR0wDQYJKoZIhvc
NAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4NDVaFw0yMD
EwMTMxNjI4NDVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBA
QUAA4IBDwAwggEKAoIBAQCWzJibKtN8Zf7LgandINhFonx99AKi44iaZkrl
MKEObE6Faf8NTUbUgK3VfJNYmCbA1baLVJ0YZJijJ7S/4o7h7eeqcJVXJkE
hWNTimWXNW/YCzTHe3SSapnSYOKmdHHRClplysL8OyyEG7pbX/aB9iAfFb/
+vUFCX5sMwFFrYxOimKJ9Pc/NRFtdv1wNw1rqWKF1ZzagWRlG4QgzRGwQ4q
uc7yO98TKikj2OPiIt7Zd46hbqQxmgGBtCkVOZIhxu77OmNrFsXmM4rZZpm
qh0UdqcpwkRojVnGXmNqeMCd6dNTnLhr9wukUYw0KgE57zCDVr9Ix+p/dA5
R1mG4RJ2XAgMBAAGjUzBRMB0GA1UdDgQWBBSbuiH2lNVrID3yt1SsFwtOFK
OnpTAfBgNVHSMEGDAWgBSbuiH2lNVrID3yt1SsFwtOFKOnpTAPBgNVHRMBA
f8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBCVWd293wWyohFqMFMHRBB
g97T2Uc1yeT0dMH4BpuOaCqQp4q5ep+uLcXEI6+3mEwm8pa/ULQCD8yLLdo
tIWlG3+h/4boFpdiPFcBDgT8kGe+0KOzB8Nt7E13QYOu12MNi10qwGrjKhd
hu1xBe4fpY5VCetVU1OLyuTsUyucQsFrtZI0SR83h+blbyoMZ7IhMngCfGU
e1bnYeWnLbpFbigKfPuVDWsMH2kgj05EAd5EgHkWbX8QA8hmcmDKfNT3YZM
8kiGQwmFrnQdq8bN0uHR8Nz+24cbmdbHcD65wlDW6GmYxi8mW+V6bAqn9pi
r/J14r4YFnqMGgjmdt81tscJV
action: member
ansible-freeipa-master/playbooks/host/hosts-member-managedby_host-absent.yml 0000664 0000000 0000000 00000000622 14600563364 0027750 0 ustar 00root root 0000000 0000000 ---
- name: Hosts member managedby_host absent
hosts: ipaserver
become: true
tasks:
- name: Ensure hosts manadegby_host is absent.
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
managedby_host: server.example.com
- name: host02.example.com
managedby_host: server.example.com
action: member
state: absent
ansible-freeipa-master/playbooks/host/hosts-member-managedby_host-present.yml 0000664 0000000 0000000 00000000600 14600563364 0030150 0 ustar 00root root 0000000 0000000 ---
- name: Hosts member managedby_host present
hosts: ipaserver
become: true
tasks:
- name: Ensure hosts manadegby_host is present.
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
managedby_host: server.example.com
- name: host02.example.com
managedby_host: server.example.com
action: member
ansible-freeipa-master/playbooks/host/hosts-member-principal-absent.yml 0000664 0000000 0000000 00000000746 14600563364 0026754 0 ustar 00root root 0000000 0000000 ---
- name: Host member principal absent
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.example.com and host02.example.com member principals host/testhost0X.example.com absent
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
principal:
- host/testhost01.example.com
- name: host02.example.com
principal:
- host/testhost02.example.com
action: member
state: absent
ansible-freeipa-master/playbooks/host/hosts-member-principal-present.yml 0000664 0000000 0000000 00000000725 14600563364 0027155 0 ustar 00root root 0000000 0000000 ---
- name: Hosts member principal present
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.example.com and host02.example.com member principals host/testhost0X.example.com present
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
principal:
- host/testhost01.example.com
- name: host02.example.com
principal:
- host/testhost02.example.com
action: member
ansible-freeipa-master/playbooks/host/hosts-present-with-certificate.yml 0000664 0000000 0000000 00000005430 14600563364 0027160 0 ustar 00root root 0000000 0000000 ---
- name: Hosts present with certificate
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.example.com and host01.example.com present with certificate
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
certificate:
- >
MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvc
NAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMD
EwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBA
QUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6X
sqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7G
PHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8H
nSVLF6Ys9+cJMJ7HuwOI+wYt3gkmspsir1tccmf4x1PP+yHJWdcXyetlFRc
mZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2Q
glidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplR
BoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldn
f13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBA
f8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4K
k+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGs
GLv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31y
kBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0
fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9m
BDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8
AN65NAdv7+js8jKUKCuyji8r3
- name: host02.example.com
certificate:
- >
MIIC/zCCAeegAwIBAgIUAWE1vaA+mZd3nwZqwWH64EbHvR0wDQYJKoZIhvc
NAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4NDVaFw0yMD
EwMTMxNjI4NDVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBA
QUAA4IBDwAwggEKAoIBAQCWzJibKtN8Zf7LgandINhFonx99AKi44iaZkrl
MKEObE6Faf8NTUbUgK3VfJNYmCbA1baLVJ0YZJijJ7S/4o7h7eeqcJVXJkE
hWNTimWXNW/YCzTHe3SSapnSYOKmdHHRClplysL8OyyEG7pbX/aB9iAfFb/
+vUFCX5sMwFFrYxOimKJ9Pc/NRFtdv1wNw1rqWKF1ZzagWRlG4QgzRGwQ4q
uc7yO98TKikj2OPiIt7Zd46hbqQxmgGBtCkVOZIhxu77OmNrFsXmM4rZZpm
qh0UdqcpwkRojVnGXmNqeMCd6dNTnLhr9wukUYw0KgE57zCDVr9Ix+p/dA5
R1mG4RJ2XAgMBAAGjUzBRMB0GA1UdDgQWBBSbuiH2lNVrID3yt1SsFwtOFK
OnpTAfBgNVHSMEGDAWgBSbuiH2lNVrID3yt1SsFwtOFKOnpTAPBgNVHRMBA
f8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBCVWd293wWyohFqMFMHRBB
g97T2Uc1yeT0dMH4BpuOaCqQp4q5ep+uLcXEI6+3mEwm8pa/ULQCD8yLLdo
tIWlG3+h/4boFpdiPFcBDgT8kGe+0KOzB8Nt7E13QYOu12MNi10qwGrjKhd
hu1xBe4fpY5VCetVU1OLyuTsUyucQsFrtZI0SR83h+blbyoMZ7IhMngCfGU
e1bnYeWnLbpFbigKfPuVDWsMH2kgj05EAd5EgHkWbX8QA8hmcmDKfNT3YZM
8kiGQwmFrnQdq8bN0uHR8Nz+24cbmdbHcD65wlDW6GmYxi8mW+V6bAqn9pi
r/J14r4YFnqMGgjmdt81tscJV
force: yes
ansible-freeipa-master/playbooks/host/hosts-present-with-managedby_host.yml 0000664 0000000 0000000 00000000636 14600563364 0027665 0 ustar 00root root 0000000 0000000 ---
- name: Host present with managedby_host
hosts: ipaserver
become: true
tasks:
- name: Ensure hosts are present with managedby_host attribute.
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
managedby_host: server.example.com
force: yes
- name: host02.example.com
managedby_host: server.example.com
force: yes
ansible-freeipa-master/playbooks/host/hosts-present-with-randompasswords.yml 0000664 0000000 0000000 00000001323 14600563364 0030121 0 ustar 00root root 0000000 0000000 ---
- name: Hosts present with random passwords
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.example.com and host01.example.com present with random passwords
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
random: yes
force: yes
- name: host02.example.com
random: yes
force: yes
register: ipahost
- name: Print generated random password for host01.example.com
ansible.builtin.debug:
var: ipahost.host["host01.example.com"].randompassword
- name: Print generated random password for host02.example.com
ansible.builtin.debug:
var: ipahost.host["host02.example.com"].randompassword
ansible-freeipa-master/playbooks/hostgroup/ 0000775 0000000 0000000 00000000000 14600563364 0021441 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/hostgroup/ensure-hostgroup-is-absent.yml 0000664 0000000 0000000 00000000355 14600563364 0027403 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
- name: Ensure host-group databases is absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
state: absent
ansible-freeipa-master/playbooks/hostgroup/ensure-hostgroup-is-present.yml 0000664 0000000 0000000 00000000471 14600563364 0027606 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
- name: Ensure host-group databases is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
ansible-freeipa-master/playbooks/hostgroup/ensure-hosts-and-hostgroups-are-absent-in-hostgroup.yml 0000664 0000000 0000000 00000000602 14600563364 0034247 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
- name: Ensure hosts and hostgroups are absent in existing databases hostgroup
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
action: member
state: absent
ansible-freeipa-master/playbooks/hostgroup/ensure-hosts-and-hostgroups-are-present-in-hostgroup.yml 0000664 0000000 0000000 00000000557 14600563364 0034464 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
- name: Ensure hosts and hostgroups are present in existing databases hostgroup
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
action: member
ansible-freeipa-master/playbooks/hostgroup/rename-hostgroup.yml 0000664 0000000 0000000 00000000417 14600563364 0025465 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: yes
tasks:
- name: Rename host-group from `databases` to `datalake`
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
rename: datalake
state: renamed
ansible-freeipa-master/playbooks/idoverridegroup/ 0000775 0000000 0000000 00000000000 14600563364 0022620 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/idoverridegroup/idoverridegroup-absent.yml 0000664 0000000 0000000 00000000505 14600563364 0030026 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: no
tasks:
- name: Ensure idoverridegroup test_group is absent in idview test_idview.
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
continue: true
state: absent
ansible-freeipa-master/playbooks/idoverridegroup/idoverridegroup-present.yml 0000664 0000000 0000000 00000000435 14600563364 0030234 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage idoverridegroup
hosts: ipaserver
become: no
tasks:
- name: Ensure idoverridegroup test_group is present in idview test_idview.
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
ansible-freeipa-master/playbooks/idoverrideuser/ 0000775 0000000 0000000 00000000000 14600563364 0022442 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/idoverrideuser/idoverrideuser-absent.yml 0000664 0000000 0000000 00000000475 14600563364 0027500 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is absent in idview test_idview
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
continue: true
state: absent
ansible-freeipa-master/playbooks/idoverrideuser/idoverrideuser-certificate-absent.yml 0000664 0000000 0000000 00000000635 14600563364 0031756 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user certificate member is absent in idview test_idview
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
action: member
state: absent
ansible-freeipa-master/playbooks/idoverrideuser/idoverrideuser-certificate-present.yml 0000664 0000000 0000000 00000000612 14600563364 0032155 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user certificate member is present in idview test_idview
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
action: member
ansible-freeipa-master/playbooks/idoverrideuser/idoverrideuser-present.yml 0000664 0000000 0000000 00000000426 14600563364 0027700 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage idoverrideuser
hosts: ipaserver
become: false
tasks:
- name: Ensure test user test_user is present in idview test_idview.
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
ansible-freeipa-master/playbooks/idp/ 0000775 0000000 0000000 00000000000 14600563364 0020163 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/idp/idp-absent.yml 0000664 0000000 0000000 00000000342 14600563364 0022733 0 ustar 00root root 0000000 0000000 ---
- name: Idp absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure github idp my-github-idp is absent
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-github-idp
state: absent
ansible-freeipa-master/playbooks/idp/idp-present.yml 0000664 0000000 0000000 00000000414 14600563364 0023137 0 ustar 00root root 0000000 0000000 ---
- name: Idp present example
hosts: ipaserver
become: no
tasks:
- name: Ensure github idp my-github-idp is present
ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-github-idp
provider: github
client_id: my-github-client-id
ansible-freeipa-master/playbooks/idrange/ 0000775 0000000 0000000 00000000000 14600563364 0021020 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/idrange/idrange-absent.yml 0000664 0000000 0000000 00000000324 14600563364 0024425 0 ustar 00root root 0000000 0000000 ---
- name: Idrange absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure idrange is absent
ipaidrange:
ipaadmin_password: SomeADMINpassword
name: id_range
state: absent
ansible-freeipa-master/playbooks/idrange/idrange-ad-posix-present.yml 0000664 0000000 0000000 00000000523 14600563364 0026354 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage idrange
hosts: ipaserver
become: no
tasks:
- name: Ensure AD-trust idrange is present
ipaidrange:
name: id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
idrange_type: ipa-ad-trust-posix
dom_name: ad.ipa.test
auto_private_groups: "false"
ansible-freeipa-master/playbooks/idrange/idrange-ad-present.yml 0000664 0000000 0000000 00000000627 14600563364 0025221 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage idrange
hosts: ipaserver
become: no
tasks:
- name: Ensure AD-trust idrange is present
ipaidrange:
ipaadmin_password: SomeADMINpassword
name: ad_id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
idrange_type: ipa-ad-trust
dom_sid: S-1-5-21-2870384104-3340008087-3140804251
auto_private_groups: "true"
ansible-freeipa-master/playbooks/idrange/idrange-present.yml 0000664 0000000 0000000 00000000471 14600563364 0024634 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage idrange
hosts: ipaserver
become: no
tasks:
- name: Ensure local idrange is present
ipaidrange:
ipaadmin_password: SomeADMINpassword
name: id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
secondary_rid_base: 200000000
ansible-freeipa-master/playbooks/idview/ 0000775 0000000 0000000 00000000000 14600563364 0020676 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/idview/idview-absent.yml 0000664 0000000 0000000 00000000340 14600563364 0024157 0 ustar 00root root 0000000 0000000 ---
- name: Idview absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure idview test_idview is absent
ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
state: absent
ansible-freeipa-master/playbooks/idview/idview-host-applied.yml 0000664 0000000 0000000 00000000455 14600563364 0025303 0 ustar 00root root 0000000 0000000 ---
- name: Idview host member applied example
hosts: ipaserver
become: no
tasks:
- name: Ensure host testhost.example.com is applied to idview test_idview
ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
host: testhost.example.com
action: member
ansible-freeipa-master/playbooks/idview/idview-host-unapplied.yml 0000664 0000000 0000000 00000000507 14600563364 0025644 0 ustar 00root root 0000000 0000000 ---
- name: Idview host member unapplied example
hosts: ipaserver
become: no
tasks:
- name: Ensure host testhost.example.com is not applied to idview test_idview
ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
host: testhost.example.com
action: member
state: absent
ansible-freeipa-master/playbooks/idview/idview-present.yml 0000664 0000000 0000000 00000000316 14600563364 0024366 0 ustar 00root root 0000000 0000000 ---
- name: Idview present example
hosts: ipaserver
become: no
tasks:
- name: Ensure idview test_idview is present
ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
ansible-freeipa-master/playbooks/install-client.yml 0000664 0000000 0000000 00000000231 14600563364 0023050 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to configure IPA clients with username/password
hosts: ipaclients
become: true
roles:
- role: ipaclient
state: present
ansible-freeipa-master/playbooks/install-cluster.yml 0000664 0000000 0000000 00000000530 14600563364 0023255 0 ustar 00root root 0000000 0000000 ---
- name: Install IPA servers
hosts: ipaserver
become: true
roles:
- role: ipaserver
state: present
- name: Install IPA replicas
hosts: ipareplicas
become: true
roles:
- role: ipareplica
state: present
- name: Install IPA clients
hosts: ipaclients
become: true
roles:
- role: ipaclient
state: present
ansible-freeipa-master/playbooks/install-replica.yml 0000664 0000000 0000000 00000000205 14600563364 0023212 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to configure IPA replicas
hosts: ipareplicas
become: true
roles:
- role: ipareplica
state: present
ansible-freeipa-master/playbooks/install-server.yml 0000664 0000000 0000000 00000000201 14600563364 0023075 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to configure IPA servers
hosts: ipaserver
become: true
roles:
- role: ipaserver
state: present
ansible-freeipa-master/playbooks/install-smartcard-clients.yml 0000664 0000000 0000000 00000000226 14600563364 0025215 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to setup smartcard for IPA clients
hosts: ipaclients
become: true
roles:
- role: ipasmartcard_client
state: present
ansible-freeipa-master/playbooks/install-smartcard-replicas.yml 0000664 0000000 0000000 00000000230 14600563364 0025351 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to setup smartcard for IPA replicas
hosts: ipareplicas
become: true
roles:
- role: ipasmartcard_server
state: present
ansible-freeipa-master/playbooks/install-smartcard-server.yml 0000664 0000000 0000000 00000000224 14600563364 0025060 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to setup smartcard for IPA server
hosts: ipaserver
become: true
roles:
- role: ipasmartcard_server
state: present
ansible-freeipa-master/playbooks/install-smartcard-servers.yml 0000664 0000000 0000000 00000000256 14600563364 0025250 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to setup smartcard for IPA server and replicas
hosts: ipaserver, ipareplicas
become: true
roles:
- role: ipasmartcard_server
state: present
ansible-freeipa-master/playbooks/location/ 0000775 0000000 0000000 00000000000 14600563364 0021217 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/location/location-absent.yml 0000664 0000000 0000000 00000000347 14600563364 0025030 0 ustar 00root root 0000000 0000000 ---
- name: Location absent test
hosts: ipaserver
become: true
tasks:
- name: Ensure location my_location1 is absent
ipalocation:
ipaadmin_password: SomeADMINpassword
name: my_location1
state: absent
ansible-freeipa-master/playbooks/location/location-present.yml 0000664 0000000 0000000 00000000325 14600563364 0025230 0 ustar 00root root 0000000 0000000 ---
- name: Location present test
hosts: ipaserver
become: true
tasks:
- name: Ensure location my_location1 is present
ipalocation:
ipaadmin_password: SomeADMINpassword
name: my_location1
ansible-freeipa-master/playbooks/netgroup/ 0000775 0000000 0000000 00000000000 14600563364 0021252 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/netgroup/netgroup-absent.yml 0000664 0000000 0000000 00000000373 14600563364 0025115 0 ustar 00root root 0000000 0000000 ---
- name: Netgroup absent example
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Ensure netgroup my_netgroup1 is absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: my_netgroup1
state: absent
ansible-freeipa-master/playbooks/netgroup/netgroup-member-absent.yml 0000664 0000000 0000000 00000000447 14600563364 0026364 0 ustar 00root root 0000000 0000000 ---
- name: Netgroup absent example
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Ensure netgroup user, "user1", is absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: TestNetgroup1
user: "user1"
action: member
state: absent
ansible-freeipa-master/playbooks/netgroup/netgroup-member-present.yml 0000664 0000000 0000000 00000000435 14600563364 0026565 0 ustar 00root root 0000000 0000000 ---
- name: Netgroup member present example
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Ensure netgroup is present with user "user1"
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: TestNetgroup1
user: user1
action: member
ansible-freeipa-master/playbooks/netgroup/netgroup-present.yml 0000664 0000000 0000000 00000000412 14600563364 0025313 0 ustar 00root root 0000000 0000000 ---
- name: Netgroup present example
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Ensure netgroup my_netgroup1 is present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: my_netgroup1
description: My netgroup 1
ansible-freeipa-master/playbooks/permission/ 0000775 0000000 0000000 00000000000 14600563364 0021577 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/permission/permission-absent.yml 0000664 0000000 0000000 00000000340 14600563364 0025761 0 ustar 00root root 0000000 0000000 ---
- name: Permission absent example
hosts: ipaserver
become: true
tasks:
- name: Ensure permission is absent
ipapermission:
ipaadmin_password: SomeADMINpassword
name: TestPerm1
state: absent
ansible-freeipa-master/playbooks/permission/permission-allow-read-employeenum.yml 0000664 0000000 0000000 00000000603 14600563364 0031073 0 ustar 00root root 0000000 0000000 ---
- name: Permission Allow Read Employee Number Example
hosts: ipaserver
become: true
tasks:
- name: Ensure permission is present with set of rights to attribute employeenumber
ipapermission:
ipaadmin_password: SomeADMINpassword
name: TestPerm1
object_type: user
right:
- read
- search
- compare
attrs: employeenumber
ansible-freeipa-master/playbooks/permission/permission-member-absent.yml 0000664 0000000 0000000 00000000476 14600563364 0027240 0 ustar 00root root 0000000 0000000 ---
- name: Permission absent example
hosts: ipaserver
become: true
tasks:
- name: Ensure permission privilege, "User Administrators", is absent
ipapermission:
ipaadmin_password: SomeADMINpassword
name: TestPerm1
privilege: "User Administrators"
action: member
state: absent
ansible-freeipa-master/playbooks/permission/permission-member-present.yml 0000664 0000000 0000000 00000000466 14600563364 0027443 0 ustar 00root root 0000000 0000000 ---
- name: Permission member present example
hosts: ipaserver
become: true
tasks:
- name: Ensure permission is present with "User Administrators" privilege
ipapermission:
ipaadmin_password: SomeADMINpassword
name: TestPerm1
privilege: "User Administrators"
action: member
ansible-freeipa-master/playbooks/permission/permission-present.yml 0000664 0000000 0000000 00000000367 14600563364 0026176 0 ustar 00root root 0000000 0000000 ---
- name: Permission present example
hosts: ipaserver
become: true
tasks:
- name: Ensure permission is present
ipapermission:
ipaadmin_password: SomeADMINpassword
name: TestPerm1
object_type: host
right: all
ansible-freeipa-master/playbooks/permission/permission-renamed.yml 0000664 0000000 0000000 00000000436 14600563364 0026126 0 ustar 00root root 0000000 0000000 ---
- name: Permission present example
hosts: ipaserver
become: true
tasks:
- name: Ensure permission TestPerm1 is renamed to TestPermRenamed
ipapermission:
ipaadmin_password: SomeADMINpassword
name: TestPerm1
rename: TestPermRenamed
state: renamed
ansible-freeipa-master/playbooks/privilege/ 0000775 0000000 0000000 00000000000 14600563364 0021375 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/privilege/privilege-absent.yml 0000664 0000000 0000000 00000000365 14600563364 0025364 0 ustar 00root root 0000000 0000000 ---
- name: Privilege absent example
hosts: ipaserver
become: true
tasks:
- name: Ensure privilege "Broad Privilege" is absent
ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
state: absent
ansible-freeipa-master/playbooks/privilege/privilege-member-absent.yml 0000664 0000000 0000000 00000000521 14600563364 0026623 0 ustar 00root root 0000000 0000000 ---
- name: Privilege absent example
hosts: ipaserver
become: true
tasks:
- name: Ensure privilege "Broad Privilege" permission is absent
ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
permission:
- "System: Write IPA Configuration"
action: member
state: absent
ansible-freeipa-master/playbooks/privilege/privilege-member-present.yml 0000664 0000000 0000000 00000000627 14600563364 0027036 0 ustar 00root root 0000000 0000000 ---
- name: Privilege member present example
hosts: ipaserver
become: true
tasks:
- name: Ensure privilege "Broad Privilege" permissions are present
ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
permission:
- "System: Write IPA Configuration"
- "System: Write DNS Configuration"
- "System: Update DNS Entries"
action: member
ansible-freeipa-master/playbooks/privilege/privilege-present.yml 0000664 0000000 0000000 00000000404 14600563364 0025562 0 ustar 00root root 0000000 0000000 ---
- name: Privilege present example
hosts: ipaserver
become: true
tasks:
- name: Ensure privilege Broad Privilege is present
ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
description: Broad Privilege
ansible-freeipa-master/playbooks/pwpolicy/ 0000775 0000000 0000000 00000000000 14600563364 0021255 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/pwpolicy/pwpolicy_absent.yml 0000664 0000000 0000000 00000000351 14600563364 0025201 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure absence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
name: ops
state: absent
ansible-freeipa-master/playbooks/pwpolicy/pwpolicy_grace_limit.yml 0000664 0000000 0000000 00000000347 14600563364 0026211 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage password policy
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Set password policy grace limit.
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
gracelimit: 3
ansible-freeipa-master/playbooks/pwpolicy/pwpolicy_password_check.yml 0000664 0000000 0000000 00000000446 14600563364 0026731 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage password policy
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Set password checking parameters.
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
maxrepeat: 2
maxsequence: 3
dictcheck: yes
usercheck: yes
ansible-freeipa-master/playbooks/pwpolicy/pwpolicy_present.yml 0000664 0000000 0000000 00000000601 14600563364 0025403 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure presence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
name: ops
minlife: 7
maxlife: 49
history: 5
priority: 1
lockouttime: 300
minlength: 8
minclasses: 5
maxfail: 3
failinterval: 5
ansible-freeipa-master/playbooks/remove-all-backups-from-server.yml 0000664 0000000 0000000 00000000256 14600563364 0026073 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to remove all backups from IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name: all
roles:
- role: ipabackup
state: absent
ansible-freeipa-master/playbooks/remove-backup-from-server.yml 0000664 0000000 0000000 00000000302 14600563364 0025132 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to remove backup from IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name: ipa-full-2020-10-22-11-11-44
roles:
- role: ipabackup
state: absent
ansible-freeipa-master/playbooks/restore-server-from-controller.yml 0000664 0000000 0000000 00000000450 14600563364 0026242 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to restore IPA server from controller
hosts: ipaserver
become: true
vars:
ipabackup_name: ipaserver.el83.local_ipa-full-2020-10-22-11-11-44
ipabackup_password: SomeDMpassword
ipabackup_from_controller: yes
roles:
- role: ipabackup
state: restored
ansible-freeipa-master/playbooks/restore-server.yml 0000664 0000000 0000000 00000000343 14600563364 0023121 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to restore an IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name: ipa-full-2020-10-22-11-11-44
ipabackup_password: SomeDMpassword
roles:
- role: ipabackup
state: restored
ansible-freeipa-master/playbooks/role/ 0000775 0000000 0000000 00000000000 14600563364 0020350 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/role/role-is-absent.yml 0000664 0000000 0000000 00000000351 14600563364 0023716 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role is absent.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
state: absent
ansible-freeipa-master/playbooks/role/role-is-present.yml 0000664 0000000 0000000 00000000370 14600563364 0024123 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role is present.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
description: A role in IPA.
ansible-freeipa-master/playbooks/role/role-member-group-absent.yml 0000664 0000000 0000000 00000000461 14600563364 0025706 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role member 'group' is absent.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
group:
- group01
action: member
state: absent
ansible-freeipa-master/playbooks/role/role-member-group-present.yml 0000664 0000000 0000000 00000000436 14600563364 0026114 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role member 'group' is present.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
group:
- group01
action: member
ansible-freeipa-master/playbooks/role/role-member-host-absent.yml 0000664 0000000 0000000 00000000472 14600563364 0025531 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role member 'host' is absent.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
host:
- host01.example.com
action: member
state: absent
ansible-freeipa-master/playbooks/role/role-member-host-present.yml 0000664 0000000 0000000 00000000447 14600563364 0025737 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role member 'host' is present.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
host:
- host01.example.com
action: member
ansible-freeipa-master/playbooks/role/role-member-hostgroup-absent.yml 0000664 0000000 0000000 00000000475 14600563364 0026611 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role member 'hostgroup' is absent.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
hostgroup:
- hostgroup01
action: member
state: absent
ansible-freeipa-master/playbooks/role/role-member-hostgroup-present.yml 0000664 0000000 0000000 00000000452 14600563364 0027010 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role member 'hostgroup' is present.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
hostgroup:
- hostgroup01
action: member
ansible-freeipa-master/playbooks/role/role-member-privilege-absent.yml 0000664 0000000 0000000 00000000542 14600563364 0026540 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role member 'privilege' is absent.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
privilege:
- Group Administrators
- User Administrators
action: member
state: absent
ansible-freeipa-master/playbooks/role/role-member-privilege-present.yml 0000664 0000000 0000000 00000000517 14600563364 0026746 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role member 'privilege' is present.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
privilege:
- Group Administrators
- User Administrators
action: member
ansible-freeipa-master/playbooks/role/role-member-service-absent.yml 0000664 0000000 0000000 00000000502 14600563364 0026206 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role member 'service' is absent.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
service:
- http/www.example.com
action: member
state: absent
ansible-freeipa-master/playbooks/role/role-member-service-present.yml 0000664 0000000 0000000 00000000444 14600563364 0026417 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role member 'service' is present.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
service:
- service01
action: member
ansible-freeipa-master/playbooks/role/role-member-user-absent.yml 0000664 0000000 0000000 00000000455 14600563364 0025533 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role member 'user' is absent.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
user:
- pinky
action: member
state: absent
ansible-freeipa-master/playbooks/role/role-member-user-present.yml 0000664 0000000 0000000 00000000432 14600563364 0025732 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role member 'user' is present.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
user:
- pinky
action: member
ansible-freeipa-master/playbooks/role/role-members-absent.yml 0000664 0000000 0000000 00000000774 14600563364 0024746 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role member.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role members are absent.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
user:
- pinky
group:
- group01
host:
- host01.example.com
hostgroup:
- hostgroup01
privilege:
- Group Administrators
- User Administrators
service:
- service01
action: member
state: absent
ansible-freeipa-master/playbooks/role/role-members-present.yml 0000664 0000000 0000000 00000000757 14600563364 0025153 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role with members.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Ensure role members are present.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
user:
- pinky
group:
- group01
host:
- host01.example.com
hostgroup:
- hostgroup01
privilege:
- Group Administrators
- User Administrators
service:
- service01
action: member
ansible-freeipa-master/playbooks/role/role-rename.yml 0000664 0000000 0000000 00000000345 14600563364 0023303 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA role.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Rename role.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
rename: anotherrole
ansible-freeipa-master/playbooks/selfservice/ 0000775 0000000 0000000 00000000000 14600563364 0021721 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/selfservice/selfservice-absent.yml 0000664 0000000 0000000 00000000407 14600563364 0026231 0 ustar 00root root 0000000 0000000 ---
- name: Selfservice absent
hosts: ipaserver
become: true
tasks:
- name: Ensure selfservice "basic manager attributes" is absent
ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
state: absent
ansible-freeipa-master/playbooks/selfservice/selfservice-member-absent.yml 0000664 0000000 0000000 00000000637 14600563364 0027503 0 ustar 00root root 0000000 0000000 ---
- name: Selfservice member absent
hosts: ipaserver
become: true
tasks:
- name: Ensure selfservice "basic manager attributes" member attributes businesscategory and departmentnumber are absent
ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- businesscategory
- departmentnumber
action: member
state: absent
ansible-freeipa-master/playbooks/selfservice/selfservice-member-present.yml 0000664 0000000 0000000 00000000535 14600563364 0027704 0 ustar 00root root 0000000 0000000 ---
- name: Selfservice member present
hosts: ipaserver
become: true
tasks:
- name: Ensure selfservice "basic manager attributes" member attribute departmentnumber is present
ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- departmentnumber
action: member
ansible-freeipa-master/playbooks/selfservice/selfservice-present.yml 0000664 0000000 0000000 00000000466 14600563364 0026442 0 ustar 00root root 0000000 0000000 ---
- name: Selfservice present
hosts: ipaserver
become: true
tasks:
- name: Ensure selfservice "basic manager attributes" is present
ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
ansible-freeipa-master/playbooks/server/ 0000775 0000000 0000000 00000000000 14600563364 0020715 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/server/server-absent-continue.yml 0000664 0000000 0000000 00000000446 14600563364 0026046 0 ustar 00root root 0000000 0000000 ---
- name: Server absent continuous mode example
hosts: ipaserver
become: true
tasks:
- name: Ensure server "absent.example.com" is absent continuous mode
ipaserver:
ipaadmin_password: SomeADMINpassword
name: absent.example.com
continue: yes
state: absent
ansible-freeipa-master/playbooks/server/server-absent-force.yml 0000664 0000000 0000000 00000000431 14600563364 0025312 0 ustar 00root root 0000000 0000000 ---
- name: Server absent with force example
hosts: ipaserver
become: true
tasks:
- name: Ensure server "absent.example.com" is absent with force
ipaserver:
ipaadmin_password: SomeADMINpassword
name: absent.example.com
force: yes
state: absent
ansible-freeipa-master/playbooks/server/server-absent-ignore_last_of_role.yml 0000664 0000000 0000000 00000000477 14600563364 0030241 0 ustar 00root root 0000000 0000000 ---
- name: Server absent with last of role skip example
hosts: ipaserver
become: true
tasks:
- name: Ensure server "absent.example.com" is absent with last of role skip
ipaserver:
ipaadmin_password: SomeADMINpassword
name: absent.example.com
ignore_last_of_role: yes
state: absent
ansible-freeipa-master/playbooks/server/server-absent-ignore_topology_disconnect.yml 0000664 0000000 0000000 00000000536 14600563364 0031652 0 ustar 00root root 0000000 0000000 ---
- name: Server absent with ignoring topology disconnects example
hosts: ipaserver
become: true
tasks:
- name: Ensure server "absent.example.com" is absent with ignoring topology disconnects
ipaserver:
ipaadmin_password: SomeADMINpassword
name: absent.example.com
ignore_topology_disconnect: yes
state: absent
ansible-freeipa-master/playbooks/server/server-absent.yml 0000664 0000000 0000000 00000000362 14600563364 0024221 0 ustar 00root root 0000000 0000000 ---
- name: Server absent example
hosts: ipaserver
become: true
tasks:
- name: Ensure server "absent.example.com" is absent
ipaserver:
ipaadmin_password: SomeADMINpassword
name: absent.example.com
state: absent
ansible-freeipa-master/playbooks/server/server-hidden.yml 0000664 0000000 0000000 00000000373 14600563364 0024202 0 ustar 00root root 0000000 0000000 ---
- name: Server hidden example
hosts: ipaserver
become: true
tasks:
- name: Ensure server "ipareplica1.example.com" is hidden
ipaserver:
ipaadmin_password: SomeADMINpassword
name: ipareplica1.example.com
hidden: True
ansible-freeipa-master/playbooks/server/server-location.yml 0000664 0000000 0000000 00000000471 14600563364 0024556 0 ustar 00root root 0000000 0000000 ---
- name: Server enabled example
hosts: ipaserver
become: true
tasks:
- name: Ensure server "{{ 'ipareplica1.' + ipaserver_domain }}" with location "mylocation"
ipaserver:
ipaadmin_password: SomeADMINpassword
name: "{{ 'ipareplica1.' + ipaserver_domain }}"
location: "mylocation"
ansible-freeipa-master/playbooks/server/server-no-location.yml 0000664 0000000 0000000 00000000407 14600563364 0025167 0 ustar 00root root 0000000 0000000 ---
- name: Server no location example
hosts: ipaserver
become: true
tasks:
- name: Ensure server "ipareplica1.example.com" with no location
ipaserver:
ipaadmin_password: SomeADMINpassword
name: ipareplica1.example.com
location: ""
ansible-freeipa-master/playbooks/server/server-no-service-weight.yml 0000664 0000000 0000000 00000000426 14600563364 0026305 0 ustar 00root root 0000000 0000000 ---
- name: Server service weight example
hosts: ipaserver
become: true
tasks:
- name: Ensure server "ipareplica1.example.com" with no service weight
ipaserver:
ipaadmin_password: SomeADMINpassword
name: ipareplica1.example.com
service_weight: -1
ansible-freeipa-master/playbooks/server/server-not-hidden.yml 0000664 0000000 0000000 00000000401 14600563364 0024770 0 ustar 00root root 0000000 0000000 ---
- name: Server not hidden example
hosts: ipaserver
become: true
tasks:
- name: Ensure server "ipareplica1.example.com" is not hidden
ipaserver:
ipaadmin_password: SomeADMINpassword
name: ipareplica1.example.com
hidden: no
ansible-freeipa-master/playbooks/server/server-present.yml 0000664 0000000 0000000 00000000351 14600563364 0024423 0 ustar 00root root 0000000 0000000 ---
- name: Server present example
hosts: ipaserver
become: true
tasks:
- name: Ensure server "ipareplica1.exmple.com" is present
ipaserver:
ipaadmin_password: SomeADMINpassword
name: ipareplica1.example.com
ansible-freeipa-master/playbooks/server/server-service-weight.yml 0000664 0000000 0000000 00000000424 14600563364 0025671 0 ustar 00root root 0000000 0000000 ---
- name: Server service weight example
hosts: ipaserver
become: true
tasks:
- name: Ensure server "ipareplica1.example.com" with service weight 1
ipaserver:
ipaadmin_password: SomeADMINpassword
name: ipareplica1.example.com
service_weight: 1
ansible-freeipa-master/playbooks/service/ 0000775 0000000 0000000 00000000000 14600563364 0021047 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/service/service-host-is-absent.yml 0000664 0000000 0000000 00000000507 14600563364 0026072 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure management host is absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
host: "{{ groups.ipaserver[0] }}"
action: member
state: absent
ansible-freeipa-master/playbooks/service/service-host-is-present.yml 0000664 0000000 0000000 00000000464 14600563364 0026300 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure management host is present.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
host: "{{ groups.ipaserver[0] }}"
action: member
ansible-freeipa-master/playbooks/service/service-is-absent.yml 0000664 0000000 0000000 00000000401 14600563364 0025110 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure service is absent
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
state: absent
ansible-freeipa-master/playbooks/service/service-is-disabled.yml 0000664 0000000 0000000 00000000406 14600563364 0025410 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to disable IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure service is disabled
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
state: disabled
ansible-freeipa-master/playbooks/service/service-is-present-with-all-attributes.yml 0000664 0000000 0000000 00000002451 14600563364 0031226 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure service is present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
certificate:
- >
MIICBjCCAW8CFHnm32VcXaUDGfEGdDL/erPSijUAMA0GCSqGSIb3DQ
EBCwUAMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENp
dHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwHhcNMjAwMT
IzMDA1NjQ2WhcNMjEwMTIyMDA1NjQ2WjBCMQswCQYDVQQGEwJYWDEV
MBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IE
NvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDY
rdVmsr7iT3f67DM5bb1osSEe5/c91UUMEIcFq5wrgBhzVfs8iIMDVC
1yiUGTsDLJNJc4nb1tUxeR9K5fh25E6n/eWDBP75NStotjAXRU4Ahi
3FNRhWFOKesds5xNqgDk5/dY8UekJv2yUblQuZzeF8b2XFrmHuCaYu
FctzPfWwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACF+5RS8Ce0HRixG
Pu4Xd51i+Kzblg++lx8fDJ8GW5G16/Z1AsB72Hc7etJL2PksHlue/x
Cq6SA9fIfHc4TBNCiWjPSP1NhHJeYyoPiSkcYsqXuxWyoyRLbnAhBV
vhoiqZbUt3u3tGB0uMMA0yJvj07mP7Nea2KdBYVH8X1pM0V+
pac_type:
- MS-PAC
- PAD
auth_ind: otp
force: no
requires_pre_auth: yes
ok_as_delegate: no
ok_to_auth_as_delegate: no
action: service
state: present
ansible-freeipa-master/playbooks/service/service-is-present-with-host-force.yml 0000664 0000000 0000000 00000000377 14600563364 0030350 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure service is present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/ihavenodns.info
force: yes
ansible-freeipa-master/playbooks/service/service-is-present-without-host-object.yml 0000664 0000000 0000000 00000000411 14600563364 0031235 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure service is present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.ansible.com
skip_host_check: yes
ansible-freeipa-master/playbooks/service/service-is-present.yml 0000664 0000000 0000000 00000000356 14600563364 0025325 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure service is present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
ansible-freeipa-master/playbooks/service/service-member-allow_create_keytab-absent.yml 0000664 0000000 0000000 00000001173 14600563364 0031751 0 ustar 00root root 0000000 0000000 ---
- name: Service member allow_create_keytab absent
hosts: ipaserver
become: true
tasks:
- name: Service HTTP/www.example.com members allow_create_keytab absent for users, groups, hosts and hostgroups
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- host01.example.com
- host02.example.com
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
ansible-freeipa-master/playbooks/service/service-member-allow_create_keytab-present.yml 0000664 0000000 0000000 00000001151 14600563364 0032151 0 ustar 00root root 0000000 0000000 ---
- name: Service member allow_create_keytab present
hosts: ipaserver
become: true
tasks:
- name: Service HTTP/www.example.com members allow_create_keytab present for users, groups, hosts and hostgroups
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- host01.example.com
- host02.example.com
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
ansible-freeipa-master/playbooks/service/service-member-allow_retrieve_keytab-absent.yml 0000664 0000000 0000000 00000001207 14600563364 0032331 0 ustar 00root root 0000000 0000000 ---
- name: Service member allow_retrieve_keytab absent
hosts: ipaserver
become: true
tasks:
- name: Service HTTP/www.example.com members allow_retrieve_keytab absent for users, groups, hosts and hostgroups
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- host01.example.com
- host02.example.com
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
ansible-freeipa-master/playbooks/service/service-member-allow_retrieve_keytab-present.yml 0000664 0000000 0000000 00000001165 14600563364 0032540 0 ustar 00root root 0000000 0000000 ---
- name: Service member allow_retrieve_keytab present
hosts: ipaserver
become: true
tasks:
- name: Service HTTP/www.example.com members allow_retrieve_keytab present for users, groups, hosts and hostgroups
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- host01.example.com
- host02.example.com
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
ansible-freeipa-master/playbooks/service/service-member-certificate-absent.yml 0000664 0000000 0000000 00000002204 14600563364 0030227 0 ustar 00root root 0000000 0000000 ---
- name: Service certificate absent.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure service certificate is absent
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
certificate:
- >
MIICBjCCAW8CFHnm32VcXaUDGfEGdDL/erPSijUAMA0GCSqGSIb3DQ
EBCwUAMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENp
dHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwHhcNMjAwMT
IzMDA1NjQ2WhcNMjEwMTIyMDA1NjQ2WjBCMQswCQYDVQQGEwJYWDEV
MBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IE
NvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDY
rdVmsr7iT3f67DM5bb1osSEe5/c91UUMEIcFq5wrgBhzVfs8iIMDVC
1yiUGTsDLJNJc4nb1tUxeR9K5fh25E6n/eWDBP75NStotjAXRU4Ahi
3FNRhWFOKesds5xNqgDk5/dY8UekJv2yUblQuZzeF8b2XFrmHuCaYu
FctzPfWwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACF+5RS8Ce0HRixG
Pu4Xd51i+Kzblg++lx8fDJ8GW5G16/Z1AsB72Hc7etJL2PksHlue/x
Cq6SA9fIfHc4TBNCiWjPSP1NhHJeYyoPiSkcYsqXuxWyoyRLbnAhBV
vhoiqZbUt3u3tGB0uMMA0yJvj07mP7Nea2KdBYVH8X1pM0V+
action: member
state: absent
ansible-freeipa-master/playbooks/service/service-member-certificate-present.yml 0000664 0000000 0000000 00000002207 14600563364 0030436 0 ustar 00root root 0000000 0000000 ---
- name: Service certificate present.
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure service certificate is present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
certificate:
- >
MIICBjCCAW8CFHnm32VcXaUDGfEGdDL/erPSijUAMA0GCSqGSIb3DQ
EBCwUAMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENp
dHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwHhcNMjAwMT
IzMDA1NjQ2WhcNMjEwMTIyMDA1NjQ2WjBCMQswCQYDVQQGEwJYWDEV
MBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IE
NvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDY
rdVmsr7iT3f67DM5bb1osSEe5/c91UUMEIcFq5wrgBhzVfs8iIMDVC
1yiUGTsDLJNJc4nb1tUxeR9K5fh25E6n/eWDBP75NStotjAXRU4Ahi
3FNRhWFOKesds5xNqgDk5/dY8UekJv2yUblQuZzeF8b2XFrmHuCaYu
FctzPfWwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACF+5RS8Ce0HRixG
Pu4Xd51i+Kzblg++lx8fDJ8GW5G16/Z1AsB72Hc7etJL2PksHlue/x
Cq6SA9fIfHc4TBNCiWjPSP1NhHJeYyoPiSkcYsqXuxWyoyRLbnAhBV
vhoiqZbUt3u3tGB0uMMA0yJvj07mP7Nea2KdBYVH8X1pM0V+
action: member
state: present
ansible-freeipa-master/playbooks/service/service-member-principal-absent.yml 0000664 0000000 0000000 00000000544 14600563364 0027733 0 ustar 00root root 0000000 0000000 ---
- name: Service member principal absent
hosts: ipaserver
become: true
tasks:
- name: Service HTTP/www.example.com member principals host/test.example.com absent
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
principal:
- host/test.example.com
action: member
state: absent
ansible-freeipa-master/playbooks/service/service-member-principal-present.yml 0000664 0000000 0000000 00000000522 14600563364 0030133 0 ustar 00root root 0000000 0000000 ---
- name: Service member principal present
hosts: ipaserver
become: true
tasks:
- name: Service HTTP/www.example.com member principals host/test.example.com present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
principal:
- host/test.example.com
action: member
ansible-freeipa-master/playbooks/servicedelegationrule/ 0000775 0000000 0000000 00000000000 14600563364 0023773 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/servicedelegationrule/servicedelegationrule-absent.yml 0000664 0000000 0000000 00000000437 14600563364 0032360 0 ustar 00root root 0000000 0000000 ---
- name: Servicedelegationrule absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationrule test-delegation-rule is absent
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: test-delegation-rule
state: absent
ansible-freeipa-master/playbooks/servicedelegationrule/servicedelegationrule-present.yml 0000664 0000000 0000000 00000000415 14600563364 0032560 0 ustar 00root root 0000000 0000000 ---
- name: Servicedelegationrule present example
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationrule test-delegation-rule is present
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: test-delegation-rule
servicedelegationrule-principal-member-absent.yml 0000664 0000000 0000000 00000000614 14600563364 0035522 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/servicedelegationrule ---
- name: Servicedelegationrule principal member absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure principal member test/example.com is absent in servicedelegationrule test-delegation-rule
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: test-delegation-rule
principal: test/example.com
action: member
state: absent
servicedelegationrule-principal-member-present.yml 0000664 0000000 0000000 00000000572 14600563364 0035731 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/servicedelegationrule ---
- name: Servicedelegationrule principal member present example
hosts: ipaserver
become: no
tasks:
- name: Ensure principal member test/example.com is present in servicedelegationrule test-delegation-rule
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: test-delegation-rule
principal: test/example.com
action: member
servicedelegationrule-target-member-absent.yml 0000664 0000000 0000000 00000000561 14600563364 0035030 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/servicedelegationrule ---
- name: Servicedelegationrule absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure member test/example.com is absent in servicedelegationrule test-delegation-rule
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: test-delegation-rule
principal: test/example.com
action: member
state: absent
servicedelegationrule-target-member-present.yml 0000664 0000000 0000000 00000000546 14600563364 0035237 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/servicedelegationrule ---
- name: Servicedelegationrule member present example
hosts: ipaserver
become: no
tasks:
- name: Ensure member test/example.com is present in servicedelegationrule test-delegation-rule
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: test-delegation-rule
principal: test/example.com
action: member
ansible-freeipa-master/playbooks/servicedelegationtarget/ 0000775 0000000 0000000 00000000000 14600563364 0024312 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/servicedelegationtarget/servicedelegationtarget-absent.yml 0000664 0000000 0000000 00000000451 14600563364 0033212 0 ustar 00root root 0000000 0000000 ---
- name: Servicedelegationtarget absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationtarget test-delegation-target is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
name: test-delegation-target
state: absent
ansible-freeipa-master/playbooks/servicedelegationtarget/servicedelegationtarget-member-absent.yml 0000664 0000000 0000000 00000000573 14600563364 0034464 0 ustar 00root root 0000000 0000000 ---
- name: Servicedelegationtarget absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure member test/example.com is absent in servicedelegationtarget test-delegation-target
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
name: test-delegation-target
principal: test/example.com
action: member
state: absent
ansible-freeipa-master/playbooks/servicedelegationtarget/servicedelegationtarget-member-present.yml 0000664 0000000 0000000 00000000560 14600563364 0034664 0 ustar 00root root 0000000 0000000 ---
- name: Servicedelegationtarget member present example
hosts: ipaserver
become: no
tasks:
- name: Ensure member test/example.com is present in servicedelegationtarget test-delegation-target
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
name: test-delegation-target
principal: test/example.com
action: member
ansible-freeipa-master/playbooks/servicedelegationtarget/servicedelegationtarget-present.yml 0000664 0000000 0000000 00000000427 14600563364 0033421 0 ustar 00root root 0000000 0000000 ---
- name: Servicedelegationtarget present example
hosts: ipaserver
become: no
tasks:
- name: Ensure servicedelegationtarget test-delegation-target is present
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
name: test-delegation-target
ansible-freeipa-master/playbooks/sudocmd/ 0000775 0000000 0000000 00000000000 14600563364 0021045 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/sudocmd/ensure-sudocmd-is-absent.yml 0000664 0000000 0000000 00000000347 14600563364 0026414 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage sudo command
hosts: ipaserver
become: true
tasks:
- name: Ensure sudo command is absent
ipasudocmd:
ipaadmin_password: SomeADMINpassword
name: /usr/bin/su
state: absent
ansible-freeipa-master/playbooks/sudocmd/ensure-sudocmd-is-present.yml 0000664 0000000 0000000 00000000351 14600563364 0026613 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage sudo command
hosts: ipaserver
become: true
tasks:
- name: Ensure sudo command is present
ipasudocmd:
ipaadmin_password: SomeADMINpassword
name: /usr/bin/su
state: present
ansible-freeipa-master/playbooks/sudocmdgroup/ 0000775 0000000 0000000 00000000000 14600563364 0022122 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/sudocmdgroup/ensure-sudocmd-are-absent-in-sudocmdgroup.yml 0000664 0000000 0000000 00000000516 14600563364 0032740 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
- name: Ensure sudocmds are absent in sudocmdgroup
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member
state: absent
ansible-freeipa-master/playbooks/sudocmdgroup/ensure-sudocmd-are-present-in-sudocmdgroup.yml 0000664 0000000 0000000 00000000770 14600563364 0033146 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
- name: Ensure sudo commands are present
ipasudocmd:
ipaadmin_password: SomeADMINpassword
name:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: present
- name: Ensure sudocmdgroup is present with sudo commands.
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member
ansible-freeipa-master/playbooks/sudocmdgroup/ensure-sudocmdgroup-is-absent.yml 0000664 0000000 0000000 00000000404 14600563364 0030540 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
- name: Ensure sudocmdgroup is absent
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
name: network
state: absent
action: sudocmdgroup
ansible-freeipa-master/playbooks/sudocmdgroup/ensure-sudocmdgroup-is-present.yml 0000664 0000000 0000000 00000000550 14600563364 0030746 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
- name: Ensure sudocmdgroup sudocmds are present
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
name: network
description: Group of important commands.
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: present
ansible-freeipa-master/playbooks/sudorule/ 0000775 0000000 0000000 00000000000 14600563364 0021251 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-does-not-have-sudooption.yml 0000664 0000000 0000000 00000000443 14600563364 0032006 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure sudooption '!root' is absent in sudorule
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
sudooption: "!root"
action: member
state: absent
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-has-sudooption.yml 0000664 0000000 0000000 00000000420 14600563364 0030103 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure sudooption '!root' is present in sudorule
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
sudooption: "!root"
action: member
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-host-member-is-absent.yml 0000664 0000000 0000000 00000000427 14600563364 0031243 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure host 'server' is absent in sudorule
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
host: server
action: member
state: absent
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-host-member-is-present.yml 0000664 0000000 0000000 00000000404 14600563364 0031442 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure host 'server' is present in sudorule
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
host: server
action: member
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-hostgroup-member-is-absent.yml 0000664 0000000 0000000 00000000443 14600563364 0032316 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure hostgroup 'cluster' is absent in sudorule
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
hostgroup: cluster
action: member
state: absent
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-hostgroup-member-is-present.yml 0000664 0000000 0000000 00000000420 14600563364 0032515 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure hostgroup 'cluster' is present in sudorule
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
hostgroup: cluster
action: member
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-hostmask-member-is-absent.yml 0000664 0000000 0000000 00000000472 14600563364 0032117 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage sudorule
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Ensure hostmask network is absent in sudorule
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
hostmask: 192.168.122.37/24
action: member
state: absent
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-hostmask-member-is-present.yml 0000664 0000000 0000000 00000000447 14600563364 0032325 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage sudorule
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Ensure hostmask network is present in sudorule
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
hostmask: 192.168.122.37/24
action: member
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-is-absent.yml 0000664 0000000 0000000 00000000320 14600563364 0027013 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
tasks:
- name: Ensure sudorule command is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
state: absent
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-is-disabled.yml 0000664 0000000 0000000 00000000324 14600563364 0027312 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
tasks:
- name: Ensure sudorule command is disabled
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
state: disabled
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-is-enabled.yml 0000664 0000000 0000000 00000000322 14600563364 0027133 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
tasks:
- name: Ensure sudorule command is enabled
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
state: enabled
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-is-present-with-order.yml 0000664 0000000 0000000 00000000360 14600563364 0031305 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure sudorule is present with the given order.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
order: 2
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-is-present.yml 0000664 0000000 0000000 00000000461 14600563364 0027225 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
tasks:
- name: Ensure sudorule command is present
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
description: A test sudo rule.
allow_sudocmd: /bin/ls
deny_sudocmd: /bin/vim
state: present
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-runasuser-group-is-absent.yml 0000664 0000000 0000000 00000000532 14600563364 0032177 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage sudorule member
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Ensure sudorule 'runasuser' do not have 'ipasuers' group as runas users.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
runasuser_group: ipausers
action: member
state: absent
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-runasuser-group-is-present.yml 0000664 0000000 0000000 00000000476 14600563364 0032412 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to manage sudorule member
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Ensure sudorule 'runasuser' has 'ipasuers' group as runas users.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
runasuser_group: ipausers
action: member
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-runasuser-is-absent.yml 0000664 0000000 0000000 00000000446 14600563364 0031051 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure sudorule 'runasuser' member 'admin' is absent.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
runasuser: admin
action: member
state: absent
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-runasuser-is-present.yml 0000664 0000000 0000000 00000000423 14600563364 0031250 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure sudorule 'runasuser' member 'admin' is present.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
runasuser: admin
action: member
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-sudocmd-is-absent.yml 0000664 0000000 0000000 00000000642 14600563364 0030456 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure sudorule members are absent.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
allow_sudocmd:
- /sbin/ifconfig
deny_sudocmd:
- /usr/bin/vim
allow_sudocmdgroup:
- devops
deny_sudocmdgroup:
- users
action: member
state: absent
ansible-freeipa-master/playbooks/sudorule/ensure-sudorule-sudocmd-is-present.yml 0000664 0000000 0000000 00000000617 14600563364 0030664 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure sudorule members are present.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
allow_sudocmd:
- /sbin/ifconfig
deny_sudocmd:
- /usr/bin/vim
allow_sudocmdgroup:
- devops
deny_sudocmdgroup:
- users
action: member
ansible-freeipa-master/playbooks/topology/ 0000775 0000000 0000000 00000000000 14600563364 0021263 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/topology/add-topologysegment.yml 0000664 0000000 0000000 00000000456 14600563364 0026000 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle topologysegment
hosts: ipaserver
become: true
tasks:
- name: Add topology segment
ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: domain
left: ipareplica1.test.local
right: ipareplica2.test.local
state: present
ansible-freeipa-master/playbooks/topology/add-topologysegments.yml 0000664 0000000 0000000 00000001374 14600563364 0026163 0 ustar 00root root 0000000 0000000 ---
- name: Add topology segments
hosts: ipaserver
become: true
gather_facts: false
vars:
ipatopology_segments:
- {suffix: domain, left: replica1.test.local, right: replica2.test.local}
- {suffix: domain, left: replica2.test.local, right: replica3.test.local}
- {suffix: domain, left: replica3.test.local, right: replica4.test.local}
- {suffix: domain+ca, left: replica4.test.local, right: replica1.test.local}
tasks:
- name: Add topology segment
ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: "{{ item.suffix }}"
name: "{{ item.name | default(omit) }}"
left: "{{ item.left }}"
right: "{{ item.right }}"
state: present
loop: "{{ ipatopology_segments | default([]) }}"
ansible-freeipa-master/playbooks/topology/check-topologysegments.yml 0000664 0000000 0000000 00000001374 14600563364 0026510 0 ustar 00root root 0000000 0000000 ---
- name: Add topology segments
hosts: ipaserver
become: true
gather_facts: false
vars:
ipatopology_segments:
- {suffix: domain, left: replica1.test.local, right: replica2.test.local}
- {suffix: domain, left: replica2.test.local, right: replica3.test.local}
- {suffix: domain, left: replica3.test.local, right: replica4.test.local}
- {suffix: domain+ca, left: replica4.test.local, right: replica1.test.local}
tasks:
- name: Add topology segment
ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: "{{ item.suffix }}"
name: "{{ item.name | default(omit) }}"
left: "{{ item.left }}"
right: "{{ item.right }}"
state: checked
loop: "{{ ipatopology_segments | default([]) }}"
ansible-freeipa-master/playbooks/topology/delete-topologysegment.yml 0000664 0000000 0000000 00000000460 14600563364 0026505 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle topologysegment
hosts: ipaserver
become: true
tasks:
- name: Delete topology segment
ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: domain
left: ipareplica1.test.local
right: ipareplica2.test.local
state: absent
ansible-freeipa-master/playbooks/topology/delete-topologysegments.yml 0000664 0000000 0000000 00000001373 14600563364 0026674 0 ustar 00root root 0000000 0000000 ---
- name: Add topology segments
hosts: ipaserver
become: true
gather_facts: false
vars:
ipatopology_segments:
- {suffix: domain, left: replica1.test.local, right: replica2.test.local}
- {suffix: domain, left: replica2.test.local, right: replica3.test.local}
- {suffix: domain, left: replica3.test.local, right: replica4.test.local}
- {suffix: domain+ca, left: replica4.test.local, right: replica1.test.local}
tasks:
- name: Add topology segment
ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: "{{ item.suffix }}"
name: "{{ item.name | default(omit) }}"
left: "{{ item.left }}"
right: "{{ item.right }}"
state: absent
loop: "{{ ipatopology_segments | default([]) }}"
ansible-freeipa-master/playbooks/topology/reinitialize-topologysegment.yml 0000664 0000000 0000000 00000000534 14600563364 0027735 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle topologysegment
hosts: ipaserver
become: true
tasks:
- name: Reinitialize topology segment
ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: domain
left: ipareplica1.test.local
right: ipareplica2.test.local
direction: left-to-right
state: reinitialized
ansible-freeipa-master/playbooks/topology/verify-topologysuffix.yml 0000664 0000000 0000000 00000000350 14600563364 0026407 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle topologysuffix
hosts: ipaserver
become: true
tasks:
- name: Verify topology suffix
ipatopologysuffix:
ipaadmin_password: SomeADMINpassword
suffix: domain
state: verified
ansible-freeipa-master/playbooks/trust/ 0000775 0000000 0000000 00000000000 14600563364 0020570 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/trust/add-trust.yml 0000664 0000000 0000000 00000000453 14600563364 0023224 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to create a trust
hosts: ipaserver
become: true
tasks:
- name: Ensure the trust is present
ipatrust:
ipaadmin_password: SomeADMINpassword
realm: windows.local
admin: Administrator
password: secret_password
state: present
ansible-freeipa-master/playbooks/trust/del-trust.yml 0000664 0000000 0000000 00000000350 14600563364 0023234 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to delete trust
hosts: ipaserver
become: true
tasks:
- name: Ensure the trust is absent
ipatrust:
ipaadmin_password: SomeADMINpassword
realm: windows.local
state: absent
ansible-freeipa-master/playbooks/uninstall-client.yml 0000664 0000000 0000000 00000000203 14600563364 0023412 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to unconfigure IPA clients
hosts: ipaclients
become: true
roles:
- role: ipaclient
state: absent
ansible-freeipa-master/playbooks/uninstall-cluster.yml 0000664 0000000 0000000 00000000533 14600563364 0023623 0 ustar 00root root 0000000 0000000 ---
- name: Uninstall IPA clients
hosts: ipaclients
become: true
roles:
- role: ipaclient
state: absent
- name: Uninstall IPA replicas
hosts: ipareplicas
become: true
roles:
- role: ipareplica
state: absent
- name: Uninstall IPA servers
hosts: ipaserver
become: true
roles:
- role: ipaserver
state: absent
ansible-freeipa-master/playbooks/uninstall-replica.yml 0000664 0000000 0000000 00000000206 14600563364 0023556 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to unconfigure IPA replicas
hosts: ipareplicas
become: true
roles:
- role: ipareplica
state: absent
ansible-freeipa-master/playbooks/uninstall-server.yml 0000664 0000000 0000000 00000000202 14600563364 0023441 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to unconfigure IPA servers
hosts: ipaserver
become: true
roles:
- role: ipaserver
state: absent
ansible-freeipa-master/playbooks/user/ 0000775 0000000 0000000 00000000000 14600563364 0020365 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/user/add-user-external-idp.yml 0000664 0000000 0000000 00000000416 14600563364 0025207 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Create user associated with an external IdP
ipauser:
ipaadmin_password: SomeADMINpassword
name: idpuser
idp: keycloak
idp_user_id: idpuser@exemple.com
ansible-freeipa-master/playbooks/user/add-user.yml 0000664 0000000 0000000 00000000635 14600563364 0022620 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Create user pinky
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
first: pinky
last: Acme
uid: 10001
gid: 100
phone: "+555123457"
email: pinky@acme.com
passwordexpiration: "2023-01-19 23:59:59"
password: "no-brain"
update_password: on_create
ansible-freeipa-master/playbooks/user/delete-preserve-user.yml 0000664 0000000 0000000 00000000354 14600563364 0025161 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Delete and preserve user pinky
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
preserve: yes
state: absent
ansible-freeipa-master/playbooks/user/delete-user.yml 0000664 0000000 0000000 00000000313 14600563364 0023323 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Remove user pinky
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: absent
ansible-freeipa-master/playbooks/user/disable-user.yml 0000664 0000000 0000000 00000000316 14600563364 0023467 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Disable user pinky
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: disabled
ansible-freeipa-master/playbooks/user/enable-user.yml 0000664 0000000 0000000 00000000314 14600563364 0023310 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Enable user pinky
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: enabled
ansible-freeipa-master/playbooks/user/ensure_user_with_randompassword.yml 0000664 0000000 0000000 00000000661 14600563364 0027630 0 ustar 00root root 0000000 0000000 ---
- name: Ensure user with random password
hosts: ipaserver
become: true
tasks:
- name: User user1 present with random password
ipauser:
ipaadmin_password: SomeADMINpassword
name: user1
first: first1
last: last1
random: yes
update_password: on_create
register: ipauser
- name: Print generated random password
ansible.builtin.debug:
var: ipauser.user.randompassword
ansible-freeipa-master/playbooks/user/ensure_users_with_randompasswords.yml 0000664 0000000 0000000 00000001225 14600563364 0030173 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
tasks:
- name: Users user1 and user1 present with random password
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
first: first1
last: last1
random: yes
- name: user2
first: first2
last: last2
random: yes
update_password: on_create
register: ipauser
- name: Print generated random password for user1
ansible.builtin.debug:
var: ipauser.user.user1.randompassword
- name: Print generated random password for user2
ansible.builtin.debug:
var: ipauser.user.user2.randompassword
ansible-freeipa-master/playbooks/user/smb-attributes.yml 0000664 0000000 0000000 00000000677 14600563364 0024067 0 ustar 00root root 0000000 0000000 ---
- name: Plabook to handle users
hosts: ipaserver
become: false
gather_facts: false
tasks:
- name: Ensure user 'smbuser' is present with smb attributes
ipauser:
ipaadmin_password: SomeADMINpassword
name: smbuser
first: SMB
last: User
smb_logon_script: N:\logonscripts\startup
smb_profile_path: \\server\profiles\some_profile
smb_home_dir: \\users\home\smbuser
smb_home_drive: "U:"
ansible-freeipa-master/playbooks/user/undelete-user.yml 0000664 0000000 0000000 00000000332 14600563364 0023667 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Undelete preserved user pinky
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: undeleted
ansible-freeipa-master/playbooks/user/unlock-users.yml 0000664 0000000 0000000 00000000336 14600563364 0023544 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Unlock users pinky and brain
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky,brain
state: unlocked
ansible-freeipa-master/playbooks/user/user_certificate_absent.yml 0000664 0000000 0000000 00000007655 14600563364 0026001 0 ustar 00root root 0000000 0000000 ---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: User test cert absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
action: member
certificate:
- >
MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZ
IhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4Mz
VaFw0yMDEwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GC
SqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXN
lzdpPOQDSwrhKH6XsqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9f
kGv6yJP6c7IAFjLeec7GPHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8P
uzw/+xA9EJrrodnJPPsE6E8HnSVLF6Ys9+cJMJ7HuwOI+wYt3gkmsps
ir1tccmf4x1PP+yHJWdcXyetlFRcmZ8gspjqOR2jb89xSQsh8gcyDW6
rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2QglidlLGpAlvHUUS+xCigW73
cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplRBoDlQl6DnAgMBAAGjUz
BRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldnf13TAfBgNVHSMEG
DAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBAf8EBTADAQH/
MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4Kk+RNRmh
sH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGsGLv
6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31
ykBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17I
j2cH0fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQC
LqJKYfJ9mBDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9
Wls5n1BIQs+M8AN65NAdv7+js8jKUKCuyji8r3
- >
MIIC/zCCAeegAwIBAgIUAWE1vaA+mZd3nwZqwWH64EbHvR0wDQYJKoZ
IhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4ND
VaFw0yMDEwMTMxNjI4NDVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GC
SqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWzJibKtN8Zf7LgandINhF
onx99AKi44iaZkrlMKEObE6Faf8NTUbUgK3VfJNYmCbA1baLVJ0YZJi
jJ7S/4o7h7eeqcJVXJkEhWNTimWXNW/YCzTHe3SSapnSYOKmdHHRClp
lysL8OyyEG7pbX/aB9iAfFb/+vUFCX5sMwFFrYxOimKJ9Pc/NRFtdv1
wNw1rqWKF1ZzagWRlG4QgzRGwQ4quc7yO98TKikj2OPiIt7Zd46hbqQ
xmgGBtCkVOZIhxu77OmNrFsXmM4rZZpmqh0UdqcpwkRojVnGXmNqeMC
d6dNTnLhr9wukUYw0KgE57zCDVr9Ix+p/dA5R1mG4RJ2XAgMBAAGjUz
BRMB0GA1UdDgQWBBSbuiH2lNVrID3yt1SsFwtOFKOnpTAfBgNVHSMEG
DAWgBSbuiH2lNVrID3yt1SsFwtOFKOnpTAPBgNVHRMBAf8EBTADAQH/
MA0GCSqGSIb3DQEBCwUAA4IBAQBCVWd293wWyohFqMFMHRBBg97T2Uc
1yeT0dMH4BpuOaCqQp4q5ep+uLcXEI6+3mEwm8pa/ULQCD8yLLdotIW
lG3+h/4boFpdiPFcBDgT8kGe+0KOzB8Nt7E13QYOu12MNi10qwGrjKh
dhu1xBe4fpY5VCetVU1OLyuTsUyucQsFrtZI0SR83h+blbyoMZ7IhMn
gCfGUe1bnYeWnLbpFbigKfPuVDWsMH2kgj05EAd5EgHkWbX8QA8hmcm
DKfNT3YZM8kiGQwmFrnQdq8bN0uHR8Nz+24cbmdbHcD65wlDW6GmYxi
8mW+V6bAqn9pir/J14r4YFnqMGgjmdt81tscJV
- >
MIIC/zCCAeegAwIBAgIUTC33WUoYGFoIVGMwgjbc5J6xCyowDQYJKoZ
IhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4NT
JaFw0yMDEwMTMxNjI4NTJaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GC
SqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCA+6P2eieXHaVJivtWif7
SntjjkJm0juRKRRGsT3wt+zCZqoDe8zylTBN0mse/POWXdC+zXRMC2X
/c4V10kgrvWbnNdFdUFfBUphiXSoqnUYHZ6Ta+b4UTzC2tECSUEnSCz
9n1ofHnyqDyT9FELzVkRkQqexD+BFgZTF39R4q8BA4bWKQy94Kgvb+I
P77+ou4fhkBLI1MX5nkWa3Oyu4TMzT/tqgPE70hk8wQzUU2aiwJ7Ism
nWE6Ysk7c4DYMJQF/51bi2ByZWERNjyBY6L+ZV90aL4UFR9O+Pw9Hat
fHVBRdmzSkKJOr9iu4summWgH0QYDmbkdhGwYvup0EmEfAgMBAAGjUz
BRMB0GA1UdDgQWBBSJCQ8ho0Ppe0khVhgiMqsvlgxIjzAfBgNVHSMEG
DAWgBSJCQ8ho0Ppe0khVhgiMqsvlgxIjzAPBgNVHRMBAf8EBTADAQH/
MA0GCSqGSIb3DQEBCwUAA4IBAQAILLPnau32r/YoOVCVWQotGtySy36
aFlHa3T8IkSpatNCPIf3U0FWS6TVYBwY0PBfdqWBkvCuJTupLh0OEP4
TCsDa5pJGOK7blyfiAfcHajqyouACSVNlG63EPvB63h4H4F4HJnhDd4
z7pVC/WPB8w5GTBJNjELmeWfH7nj7lu8UkOdLhzTKL40RPs0k4l09yY
BmZqqExxGsSfvRBQcrwlAsvQ0E/cTNGbyzOKs3SbOM2WEHye6xNEsey
01icYcjfjqvEd6mw3+WOUeJAuDH9/EOloFM2iz5Xp31Ig3WT0RVy+lM
riG9GesPpFBs2xp9wQCXLNIkpbHKyYs3voMyBH
state: absent
ansible-freeipa-master/playbooks/user/user_certificate_present.yml 0000664 0000000 0000000 00000007632 14600563364 0026200 0 ustar 00root root 0000000 0000000 ---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: User test cert present
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
action: member
certificate:
- >
MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZ
IhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4Mz
VaFw0yMDEwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GC
SqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXN
lzdpPOQDSwrhKH6XsqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9f
kGv6yJP6c7IAFjLeec7GPHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8P
uzw/+xA9EJrrodnJPPsE6E8HnSVLF6Ys9+cJMJ7HuwOI+wYt3gkmsps
ir1tccmf4x1PP+yHJWdcXyetlFRcmZ8gspjqOR2jb89xSQsh8gcyDW6
rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2QglidlLGpAlvHUUS+xCigW73
cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplRBoDlQl6DnAgMBAAGjUz
BRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldnf13TAfBgNVHSMEG
DAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBAf8EBTADAQH/
MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4Kk+RNRmh
sH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGsGLv
6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31
ykBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17I
j2cH0fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQC
LqJKYfJ9mBDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9
Wls5n1BIQs+M8AN65NAdv7+js8jKUKCuyji8r3
- >
MIIC/zCCAeegAwIBAgIUAWE1vaA+mZd3nwZqwWH64EbHvR0wDQYJKoZ
IhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4ND
VaFw0yMDEwMTMxNjI4NDVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GC
SqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWzJibKtN8Zf7LgandINhF
onx99AKi44iaZkrlMKEObE6Faf8NTUbUgK3VfJNYmCbA1baLVJ0YZJi
jJ7S/4o7h7eeqcJVXJkEhWNTimWXNW/YCzTHe3SSapnSYOKmdHHRClp
lysL8OyyEG7pbX/aB9iAfFb/+vUFCX5sMwFFrYxOimKJ9Pc/NRFtdv1
wNw1rqWKF1ZzagWRlG4QgzRGwQ4quc7yO98TKikj2OPiIt7Zd46hbqQ
xmgGBtCkVOZIhxu77OmNrFsXmM4rZZpmqh0UdqcpwkRojVnGXmNqeMC
d6dNTnLhr9wukUYw0KgE57zCDVr9Ix+p/dA5R1mG4RJ2XAgMBAAGjUz
BRMB0GA1UdDgQWBBSbuiH2lNVrID3yt1SsFwtOFKOnpTAfBgNVHSMEG
DAWgBSbuiH2lNVrID3yt1SsFwtOFKOnpTAPBgNVHRMBAf8EBTADAQH/
MA0GCSqGSIb3DQEBCwUAA4IBAQBCVWd293wWyohFqMFMHRBBg97T2Uc
1yeT0dMH4BpuOaCqQp4q5ep+uLcXEI6+3mEwm8pa/ULQCD8yLLdotIW
lG3+h/4boFpdiPFcBDgT8kGe+0KOzB8Nt7E13QYOu12MNi10qwGrjKh
dhu1xBe4fpY5VCetVU1OLyuTsUyucQsFrtZI0SR83h+blbyoMZ7IhMn
gCfGUe1bnYeWnLbpFbigKfPuVDWsMH2kgj05EAd5EgHkWbX8QA8hmcm
DKfNT3YZM8kiGQwmFrnQdq8bN0uHR8Nz+24cbmdbHcD65wlDW6GmYxi
8mW+V6bAqn9pir/J14r4YFnqMGgjmdt81tscJV
- >
MIIC/zCCAeegAwIBAgIUTC33WUoYGFoIVGMwgjbc5J6xCyowDQYJKoZ
IhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4NT
JaFw0yMDEwMTMxNjI4NTJaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GC
SqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCA+6P2eieXHaVJivtWif7
SntjjkJm0juRKRRGsT3wt+zCZqoDe8zylTBN0mse/POWXdC+zXRMC2X
/c4V10kgrvWbnNdFdUFfBUphiXSoqnUYHZ6Ta+b4UTzC2tECSUEnSCz
9n1ofHnyqDyT9FELzVkRkQqexD+BFgZTF39R4q8BA4bWKQy94Kgvb+I
P77+ou4fhkBLI1MX5nkWa3Oyu4TMzT/tqgPE70hk8wQzUU2aiwJ7Ism
nWE6Ysk7c4DYMJQF/51bi2ByZWERNjyBY6L+ZV90aL4UFR9O+Pw9Hat
fHVBRdmzSkKJOr9iu4summWgH0QYDmbkdhGwYvup0EmEfAgMBAAGjUz
BRMB0GA1UdDgQWBBSJCQ8ho0Ppe0khVhgiMqsvlgxIjzAfBgNVHSMEG
DAWgBSJCQ8ho0Ppe0khVhgiMqsvlgxIjzAPBgNVHRMBAf8EBTADAQH/
MA0GCSqGSIb3DQEBCwUAA4IBAQAILLPnau32r/YoOVCVWQotGtySy36
aFlHa3T8IkSpatNCPIf3U0FWS6TVYBwY0PBfdqWBkvCuJTupLh0OEP4
TCsDa5pJGOK7blyfiAfcHajqyouACSVNlG63EPvB63h4H4F4HJnhDd4
z7pVC/WPB8w5GTBJNjELmeWfH7nj7lu8UkOdLhzTKL40RPs0k4l09yY
BmZqqExxGsSfvRBQcrwlAsvQ0E/cTNGbyzOKs3SbOM2WEHye6xNEsey
01icYcjfjqvEd6mw3+WOUeJAuDH9/EOloFM2iz5Xp31Ig3WT0RVy+lM
riG9GesPpFBs2xp9wQCXLNIkpbHKyYs3voMyBH
ansible-freeipa-master/playbooks/user/user_present.yml 0000664 0000000 0000000 00000002011 14600563364 0023620 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: User pinky present
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
uid: 10001
gid: 100
phone: "+555123457"
email: pinky@acme.com
principalexpiration: "20220119235959"
passwordexpiration: "2022-01-19 23:59:59"
first: pinky
last: Acme
initials: pa
principal: pa
random: yes
city: PinkyCity
userstate: PinkyState
postalcode: 321
mobile: "+555123458,+555123459"
pager: "+555123450,+555123451"
fax: "+555123452,+555123453"
orgunit: PinkyOrgUnit
manager: manager1,manager2
update_password: on_create
carlicense: PinkyCarLicense1,PinkyCarLicense2
userauthtype: password,radius,otp
userclass: PinkyUserClass
departmentnumber: "1234"
employeenumber: "0815"
employeetype: "PinkyExmployeeType"
preferredlanguage: "en"
noprivate: yes
nomembers: false
ansible-freeipa-master/playbooks/user/users_absent.yml 0000664 0000000 0000000 00000001454 14600563364 0023611 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Users user1..10 absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
givenname: user1
last: Last
- name: user2
first: user2
last: Last
- name: user3
first: user3
last: Last
- name: user4
first: user4
last: Last
- name: user5
first: user5
last: Last
- name: user6
first: user6
last: Last
- name: user7
first: user7
last: Last
- name: user8
first: user8
last: Last
- name: user9
first: user9
last: Last
- name: user10
first: user10
last: Last
state: absent
ansible-freeipa-master/playbooks/user/users_certificate_absent.yml 0000664 0000000 0000000 00000007651 14600563364 0026160 0 ustar 00root root 0000000 0000000 ---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: User test cert absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certificate:
- >
MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZ
IhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4Mz
VaFw0yMDEwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GC
SqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXN
lzdpPOQDSwrhKH6XsqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9f
kGv6yJP6c7IAFjLeec7GPHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8P
uzw/+xA9EJrrodnJPPsE6E8HnSVLF6Ys9+cJMJ7HuwOI+wYt3gkmsps
ir1tccmf4x1PP+yHJWdcXyetlFRcmZ8gspjqOR2jb89xSQsh8gcyDW6
rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2QglidlLGpAlvHUUS+xCigW73
cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplRBoDlQl6DnAgMBAAGjUz
BRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldnf13TAfBgNVHSMEG
DAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBAf8EBTADAQH/
MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4Kk+RNRmh
sH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGsGLv
6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31
ykBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17I
j2cH0fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQC
LqJKYfJ9mBDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9
Wls5n1BIQs+M8AN65NAdv7+js8jKUKCuyji8r3
- >
MIIC/zCCAeegAwIBAgIUAWE1vaA+mZd3nwZqwWH64EbHvR0wDQYJKoZ
IhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4ND
VaFw0yMDEwMTMxNjI4NDVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GC
SqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWzJibKtN8Zf7LgandINhF
onx99AKi44iaZkrlMKEObE6Faf8NTUbUgK3VfJNYmCbA1baLVJ0YZJi
jJ7S/4o7h7eeqcJVXJkEhWNTimWXNW/YCzTHe3SSapnSYOKmdHHRClp
lysL8OyyEG7pbX/aB9iAfFb/+vUFCX5sMwFFrYxOimKJ9Pc/NRFtdv1
wNw1rqWKF1ZzagWRlG4QgzRGwQ4quc7yO98TKikj2OPiIt7Zd46hbqQ
xmgGBtCkVOZIhxu77OmNrFsXmM4rZZpmqh0UdqcpwkRojVnGXmNqeMC
d6dNTnLhr9wukUYw0KgE57zCDVr9Ix+p/dA5R1mG4RJ2XAgMBAAGjUz
BRMB0GA1UdDgQWBBSbuiH2lNVrID3yt1SsFwtOFKOnpTAfBgNVHSMEG
DAWgBSbuiH2lNVrID3yt1SsFwtOFKOnpTAPBgNVHRMBAf8EBTADAQH/
MA0GCSqGSIb3DQEBCwUAA4IBAQBCVWd293wWyohFqMFMHRBBg97T2Uc
1yeT0dMH4BpuOaCqQp4q5ep+uLcXEI6+3mEwm8pa/ULQCD8yLLdotIW
lG3+h/4boFpdiPFcBDgT8kGe+0KOzB8Nt7E13QYOu12MNi10qwGrjKh
dhu1xBe4fpY5VCetVU1OLyuTsUyucQsFrtZI0SR83h+blbyoMZ7IhMn
gCfGUe1bnYeWnLbpFbigKfPuVDWsMH2kgj05EAd5EgHkWbX8QA8hmcm
DKfNT3YZM8kiGQwmFrnQdq8bN0uHR8Nz+24cbmdbHcD65wlDW6GmYxi
8mW+V6bAqn9pir/J14r4YFnqMGgjmdt81tscJV
- >
MIIC/zCCAeegAwIBAgIUTC33WUoYGFoIVGMwgjbc5J6xCyowDQYJKoZ
IhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4NT
JaFw0yMDEwMTMxNjI4NTJaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GC
SqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCA+6P2eieXHaVJivtWif7
SntjjkJm0juRKRRGsT3wt+zCZqoDe8zylTBN0mse/POWXdC+zXRMC2X
/c4V10kgrvWbnNdFdUFfBUphiXSoqnUYHZ6Ta+b4UTzC2tECSUEnSCz
9n1ofHnyqDyT9FELzVkRkQqexD+BFgZTF39R4q8BA4bWKQy94Kgvb+I
P77+ou4fhkBLI1MX5nkWa3Oyu4TMzT/tqgPE70hk8wQzUU2aiwJ7Ism
nWE6Ysk7c4DYMJQF/51bi2ByZWERNjyBY6L+ZV90aL4UFR9O+Pw9Hat
fHVBRdmzSkKJOr9iu4summWgH0QYDmbkdhGwYvup0EmEfAgMBAAGjUz
BRMB0GA1UdDgQWBBSJCQ8ho0Ppe0khVhgiMqsvlgxIjzAfBgNVHSMEG
DAWgBSJCQ8ho0Ppe0khVhgiMqsvlgxIjzAPBgNVHRMBAf8EBTADAQH/
MA0GCSqGSIb3DQEBCwUAA4IBAQAILLPnau32r/YoOVCVWQotGtySy36
aFlHa3T8IkSpatNCPIf3U0FWS6TVYBwY0PBfdqWBkvCuJTupLh0OEP4
TCsDa5pJGOK7blyfiAfcHajqyouACSVNlG63EPvB63h4H4F4HJnhDd4
z7pVC/WPB8w5GTBJNjELmeWfH7nj7lu8UkOdLhzTKL40RPs0k4l09yY
BmZqqExxGsSfvRBQcrwlAsvQ0E/cTNGbyzOKs3SbOM2WEHye6xNEsey
01icYcjfjqvEd6mw3+WOUeJAuDH9/EOloFM2iz5Xp31Ig3WT0RVy+lM
riG9GesPpFBs2xp9wQCXLNIkpbHKyYs3voMyBH
state: absent
ansible-freeipa-master/playbooks/user/users_certificate_present.yml 0000664 0000000 0000000 00000007626 14600563364 0026366 0 ustar 00root root 0000000 0000000 ---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: User test cert present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certificate:
- >
MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZ
IhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4Mz
VaFw0yMDEwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GC
SqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXN
lzdpPOQDSwrhKH6XsqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9f
kGv6yJP6c7IAFjLeec7GPHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8P
uzw/+xA9EJrrodnJPPsE6E8HnSVLF6Ys9+cJMJ7HuwOI+wYt3gkmsps
ir1tccmf4x1PP+yHJWdcXyetlFRcmZ8gspjqOR2jb89xSQsh8gcyDW6
rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2QglidlLGpAlvHUUS+xCigW73
cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplRBoDlQl6DnAgMBAAGjUz
BRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldnf13TAfBgNVHSMEG
DAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBAf8EBTADAQH/
MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4Kk+RNRmh
sH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGsGLv
6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31
ykBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17I
j2cH0fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQC
LqJKYfJ9mBDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9
Wls5n1BIQs+M8AN65NAdv7+js8jKUKCuyji8r3
- >
MIIC/zCCAeegAwIBAgIUAWE1vaA+mZd3nwZqwWH64EbHvR0wDQYJKoZ
IhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4ND
VaFw0yMDEwMTMxNjI4NDVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GC
SqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWzJibKtN8Zf7LgandINhF
onx99AKi44iaZkrlMKEObE6Faf8NTUbUgK3VfJNYmCbA1baLVJ0YZJi
jJ7S/4o7h7eeqcJVXJkEhWNTimWXNW/YCzTHe3SSapnSYOKmdHHRClp
lysL8OyyEG7pbX/aB9iAfFb/+vUFCX5sMwFFrYxOimKJ9Pc/NRFtdv1
wNw1rqWKF1ZzagWRlG4QgzRGwQ4quc7yO98TKikj2OPiIt7Zd46hbqQ
xmgGBtCkVOZIhxu77OmNrFsXmM4rZZpmqh0UdqcpwkRojVnGXmNqeMC
d6dNTnLhr9wukUYw0KgE57zCDVr9Ix+p/dA5R1mG4RJ2XAgMBAAGjUz
BRMB0GA1UdDgQWBBSbuiH2lNVrID3yt1SsFwtOFKOnpTAfBgNVHSMEG
DAWgBSbuiH2lNVrID3yt1SsFwtOFKOnpTAPBgNVHRMBAf8EBTADAQH/
MA0GCSqGSIb3DQEBCwUAA4IBAQBCVWd293wWyohFqMFMHRBBg97T2Uc
1yeT0dMH4BpuOaCqQp4q5ep+uLcXEI6+3mEwm8pa/ULQCD8yLLdotIW
lG3+h/4boFpdiPFcBDgT8kGe+0KOzB8Nt7E13QYOu12MNi10qwGrjKh
dhu1xBe4fpY5VCetVU1OLyuTsUyucQsFrtZI0SR83h+blbyoMZ7IhMn
gCfGUe1bnYeWnLbpFbigKfPuVDWsMH2kgj05EAd5EgHkWbX8QA8hmcm
DKfNT3YZM8kiGQwmFrnQdq8bN0uHR8Nz+24cbmdbHcD65wlDW6GmYxi
8mW+V6bAqn9pir/J14r4YFnqMGgjmdt81tscJV
- >
MIIC/zCCAeegAwIBAgIUTC33WUoYGFoIVGMwgjbc5J6xCyowDQYJKoZ
IhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4NT
JaFw0yMDEwMTMxNjI4NTJaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GC
SqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCA+6P2eieXHaVJivtWif7
SntjjkJm0juRKRRGsT3wt+zCZqoDe8zylTBN0mse/POWXdC+zXRMC2X
/c4V10kgrvWbnNdFdUFfBUphiXSoqnUYHZ6Ta+b4UTzC2tECSUEnSCz
9n1ofHnyqDyT9FELzVkRkQqexD+BFgZTF39R4q8BA4bWKQy94Kgvb+I
P77+ou4fhkBLI1MX5nkWa3Oyu4TMzT/tqgPE70hk8wQzUU2aiwJ7Ism
nWE6Ysk7c4DYMJQF/51bi2ByZWERNjyBY6L+ZV90aL4UFR9O+Pw9Hat
fHVBRdmzSkKJOr9iu4summWgH0QYDmbkdhGwYvup0EmEfAgMBAAGjUz
BRMB0GA1UdDgQWBBSJCQ8ho0Ppe0khVhgiMqsvlgxIjzAfBgNVHSMEG
DAWgBSJCQ8ho0Ppe0khVhgiMqsvlgxIjzAPBgNVHRMBAf8EBTADAQH/
MA0GCSqGSIb3DQEBCwUAA4IBAQAILLPnau32r/YoOVCVWQotGtySy36
aFlHa3T8IkSpatNCPIf3U0FWS6TVYBwY0PBfdqWBkvCuJTupLh0OEP4
TCsDa5pJGOK7blyfiAfcHajqyouACSVNlG63EPvB63h4H4F4HJnhDd4
z7pVC/WPB8w5GTBJNjELmeWfH7nj7lu8UkOdLhzTKL40RPs0k4l09yY
BmZqqExxGsSfvRBQcrwlAsvQ0E/cTNGbyzOKs3SbOM2WEHye6xNEsey
01icYcjfjqvEd6mw3+WOUeJAuDH9/EOloFM2iz5Xp31Ig3WT0RVy+lM
riG9GesPpFBs2xp9wQCXLNIkpbHKyYs3voMyBH
ansible-freeipa-master/playbooks/user/users_present.yml 0000664 0000000 0000000 00000001425 14600563364 0024013 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Users user1..10 present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
first: user1
last: Last
- name: user2
first: user2
last: Last
- name: user3
first: user3
last: Last
- name: user4
first: user4
last: Last
- name: user5
first: user5
last: Last
- name: user6
first: user6
last: Last
- name: user7
first: user7
last: Last
- name: user8
first: user8
last: Last
- name: user9
first: user9
last: Last
- name: user10
first: user10
last: Last
ansible-freeipa-master/playbooks/vault/ 0000775 0000000 0000000 00000000000 14600563364 0020542 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/playbooks/vault/change-password-symmetric-vault.yml 0000664 0000000 0000000 00000000667 14600563364 0027526 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to change password of symmetric vault.
hosts: ipaserver
become: yes
gather_facts: no
tasks:
- name: Create vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
- name: Change vault password.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
new_password: SomeNEWpassword
ansible-freeipa-master/playbooks/vault/data-archive-in-asymmetric-vault.yml 0000664 0000000 0000000 00000000460 14600563364 0027525 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Archive data into asymmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
username: user01
vault_data: The world of π is half rounded.
action: member
ansible-freeipa-master/playbooks/vault/data-archive-in-symmetric-vault.yml 0000664 0000000 0000000 00000000526 14600563364 0027367 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Archieve data into symmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
vault_password: SomeVAULTpassword
vault_data: The world of π is half rounded.
action: member
ansible-freeipa-master/playbooks/vault/ensure-asymetric-vault-is-absent.yml 0000664 0000000 0000000 00000000372 14600563364 0027602 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure asymmetric vault is absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
username: admin
state: absent
ansible-freeipa-master/playbooks/vault/ensure-asymetric-vault-is-present.yml 0000664 0000000 0000000 00000001311 14600563364 0030000 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure asymmetric vault is present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
username: admin
vault_public_key: >
LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlHZk1BMEdDU3FHU0liM0RR
RUJBUVVBQTRHTkFEQ0JpUUtCZ1FDdGFudjRkK3ptSTZ0T3ova1RXdGowY3Ax
RAowUENoYy8vR0pJMTUzTi9CN3UrN0h3SXlRVlZoNUlXZG1UcCtkWXYzd09y
eVpPbzYvbHN5eFJaZ2pZRDRwQ3VGCjlxM295VTFEMnFOZERYeGtSaFFETXBi
UEVSWWlHbE1jbzdhN0hIVDk1bGNQbmhObVFkb3VGdHlVbFBUVS96V1kKZldY
WTBOeU1UbUtoeFRseUV3SURBUUFCCi0tLS0tRU5EIFBVQkxJQyBLRVktLS0t
LQo=
vault_type: asymmetric
ansible-freeipa-master/playbooks/vault/ensure-service-vault-is-absent.yml 0000664 0000000 0000000 00000000420 14600563364 0027234 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure service vault is absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: svcvault
service: "HTTP/{{ groups.ipaserver[0] }}"
state: absent
ansible-freeipa-master/playbooks/vault/ensure-service-vault-is-present.yml 0000664 0000000 0000000 00000000475 14600563364 0027452 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure service vault is present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: svcvault
service: "HTTP/{{ groups.ipaserver[0] }}"
ipavaultpassword: MyVaultPassword123
state: present
ansible-freeipa-master/playbooks/vault/ensure-shared-vault-is-absent.yml 0000664 0000000 0000000 00000000365 14600563364 0027052 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure shared vault is absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: sharedvault
shared: True
state: absent
ansible-freeipa-master/playbooks/vault/ensure-shared-vault-is-present.yml 0000664 0000000 0000000 00000000442 14600563364 0027252 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure shared vault is present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: sharedvault
shared: True
ipavaultpassword: MyVaultPassword123
state: present
ansible-freeipa-master/playbooks/vault/ensure-standard-vault-is-absent.yml 0000664 0000000 0000000 00000000356 14600563364 0027404 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure vault is absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
username: admin
state: absent
ansible-freeipa-master/playbooks/vault/ensure-standard-vault-is-present.yml 0000664 0000000 0000000 00000000454 14600563364 0027607 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure standard vault is present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
vault_type: standard
username: admin
description: A standard private vault.
ansible-freeipa-master/playbooks/vault/ensure-symetric-vault-is-absent.yml 0000664 0000000 0000000 00000000370 14600563364 0027437 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure symmetric vault is absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
state: absent
ansible-freeipa-master/playbooks/vault/ensure-symetric-vault-is-present.yml 0000664 0000000 0000000 00000000415 14600563364 0027643 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure symmetric vault is present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
vault_password: SomeVAULTpassword
ansible-freeipa-master/playbooks/vault/ensure-vault-is-present-with-members.yml 0000664 0000000 0000000 00000000516 14600563364 0030411 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure vault is present, with members.
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
vault_type: standard
username: admin
users:
- user01
- user02
groups:
- ipausers
ansible-freeipa-master/playbooks/vault/ensure-vault-member-group-is-absent.yml 0000664 0000000 0000000 00000000451 14600563364 0030201 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure vault member "group" is absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: keychain
username: admin
state: absent
action: member
groups: ipausers
ansible-freeipa-master/playbooks/vault/ensure-vault-member-group-is-present.yml 0000664 0000000 0000000 00000000453 14600563364 0030407 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure vault member "group" is present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: keychain
username: admin
state: present
action: member
groups: ipausers
ansible-freeipa-master/playbooks/vault/ensure-vault-member-user-is-absent.yml 0000664 0000000 0000000 00000000474 14600563364 0030030 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure vault member "user" is absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: keychain
username: admin
state: absent
action: member
users:
- user01
- user02
ansible-freeipa-master/playbooks/vault/ensure-vault-member-user-is-present.yml 0000664 0000000 0000000 00000000446 14600563364 0030233 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure vault member "user" is present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: keychain
username: admin
state: present
action: member
users: user1
ansible-freeipa-master/playbooks/vault/ensure-vault-owner-is-absent.yml 0000664 0000000 0000000 00000000514 14600563364 0026732 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure vault owners and ownergroups are absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
owners: user01
ownergroups: ipausers
action: member
state: absent
ansible-freeipa-master/playbooks/vault/ensure-vault-owner-is-present.yml 0000664 0000000 0000000 00000000516 14600563364 0027140 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure vault owners and ownergroups are present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
owners: user01
ownergroups: ipausers
action: member
state: present
ansible-freeipa-master/playbooks/vault/password.txt 0000664 0000000 0000000 00000000022 14600563364 0023137 0 ustar 00root root 0000000 0000000 SomeVAULTpassword
ansible-freeipa-master/playbooks/vault/private.pem 0000664 0000000 0000000 00000003213 14600563364 0022716 0 ustar 00root root 0000000 0000000 -----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEArM5/f6dd/YIm/a9eoGVTW8jobEgrf9PXRA3aHsA7kJo6fB18
HD4+RVUwx/lqlkPYbUi9bXV/rJAkUwAEDOnJeqXESZ+gVCVmigRzmKWK2ad9agmY
SiqyyNxFIJvZAo0dG4CAWjYK27tLg4Ih6oGsZIDG+WVES5W89K+L0bwVjq4tshhe
DMO57unvmIKEmaBE0ewPfvkdZh5k8Gts9H4fh0fGk5tbIYa0bhwMUpL+WHOm6nbd
+n7BbaVc820TgZDO/rSYtnuXaIc6Wx0U9LXZkUmk3apMnzknNaTqguAQdTn79G8P
qrGqmyWd/E1cH2b5jzIxiGo8psL5sxWVY7WJdwIDAQABAoIBAA6e9iit14UAgx4J
vX7is9fbOtcWkB+jo94NMfxSFXgZpIMl139oQMqK97KjxsHqAaDVe7mMLH5EP96J
7M3O5g4rgl0cVWtpMrDQyZsLvqDFzBWxtCHqVPAruumUZhsSJ3lROQro8ag/w5bf
5tC5ogVq4+rsB4hBphgp1jGrsUM+E8O7DXXFH68F8WgBi725WvcjnbI9irkb0Gcq
1bCPJwN3fA1i2VWiRwVYWbNTWnDoNM9ZdYYxK0kuUkD+QtreycWPf9V49lvUi1Vp
FVNmBUDvGK3K1MwbgXRwOXhacY7Ptjkdvaeb2Qcu5RjTkruGhzUYsOP3p/cw+wKV
vzQqceECgYEA5Wz7V2SlRa2r//z+ETQkJfENJ0KDnCb0pMClCQh3jTNPA6DbhiMk
FTkcoNbqcpTiVSlvhh6TKscSgqYQUjQ/OqyG7SkjKVjQ72j5beQLxiLTtUyj1OmP
Xh9cWJXx8iQ+45cPon+kMOAIiTwiB3mmFRfQjIGve1DPUo9J+NZ4XdECgYEAwNKg
OdGYxxKtCrXVz1mdg6PDlV8qh7nxxZbPch+aMIQl1+oTCgSiw8oOYEd8g0HOdV6t
1G+IWhvPxiiWy3/AE0QhgoKk2GUsSjWSMLcJbaUzDoEHFjTLjecRlqdzo7qxRXqB
meN4L5WJYKnLC482K7hvufS+uo5fB5qwPmt13McCgYAe4TVPRP+tyjttYCr+O8tl
w/UmRKCcQu4Iwtkzxwz4V2CaN2t0uYQgyygcSfESbRGtrr8RCUp7poHKTfnCZr/f
8NrUTwYpiYfNwY5ZCSnAiG2AaIlgnfMrEwOF9OC028YPMgTrtUxvO6hKeGqIIQqG
qkbqsoXhDjZpgVnOgWeAEQKBgGuiZ0w/IqAlXbC31fUb2iBMfvXXnJ8M/dfFGmFj
IKfqbFF9WUljUxQlqya1YNzIFB5STohiBeP+2FmN+Lb5xdc7VdVLZgdhWnrGMqe8
1Kd+6uQyxCjyKZo5nQjSymtf4GqfOs8TOdieCYSK40u9koiPONa9tuXeaU+OWslN
JQqrAoGBAJ3MKOvsnQzuZVP2vz0ZqLwIE3XjRiFGveVpizq4hwOVeuNsV08JvA0t
pueNIy9klPScFc9OUdiZWkEX09BwJkVIrOHotuSB8AStO5UAntNnuyWLJEFC4Uq4
GpB8lbj9jkxSKaU7X3Gac23K9JL8euLh7E7rPuZRYa6mYN4nbKqu
-----END RSA PRIVATE KEY-----
ansible-freeipa-master/playbooks/vault/public.pem 0000664 0000000 0000000 00000000703 14600563364 0022523 0 ustar 00root root 0000000 0000000 -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArM5/f6dd/YIm/a9eoGVT
W8jobEgrf9PXRA3aHsA7kJo6fB18HD4+RVUwx/lqlkPYbUi9bXV/rJAkUwAEDOnJ
eqXESZ+gVCVmigRzmKWK2ad9agmYSiqyyNxFIJvZAo0dG4CAWjYK27tLg4Ih6oGs
ZIDG+WVES5W89K+L0bwVjq4tshheDMO57unvmIKEmaBE0ewPfvkdZh5k8Gts9H4f
h0fGk5tbIYa0bhwMUpL+WHOm6nbd+n7BbaVc820TgZDO/rSYtnuXaIc6Wx0U9LXZ
kUmk3apMnzknNaTqguAQdTn79G8PqrGqmyWd/E1cH2b5jzIxiGo8psL5sxWVY7WJ
dwIDAQAB
-----END PUBLIC KEY-----
ansible-freeipa-master/playbooks/vault/retrive-data-asymmetric-vault.yml 0000664 0000000 0000000 00000000735 14600563364 0027165 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Retrieve data from assymetric vault with a private key file.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
username: user01
private_key_file: private.pem
state: retrieved
register: result
no_log: true
- name: Display retrieved data.
ansible.builtin.debug:
msg: "Data: {{ result.vault.data }}"
ansible-freeipa-master/playbooks/vault/retrive-data-symmetric-vault.yml 0000664 0000000 0000000 00000000700 14600563364 0027014 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Retrieve data from symmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
password: SomeVAULTpassword
state: retrieved
register: result
no_log: true
- name: Display retrieved data.
ansible.builtin.debug:
msg: "Data: {{ result.vault.data }}"
ansible-freeipa-master/playbooks/vault/vault-is-present-with-password-file.yml 0000664 0000000 0000000 00000001410 14600563364 0030231 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: True
tasks:
- name: Copy file containing password to server.
ansible.builtin.copy:
src: "{{ playbook_dir }}/password.txt"
dest: "{{ ansible_facts['env'].HOME }}/password.txt"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: 0600
- name: Ensure symmetric vault exists with password from file.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
vault_type: symmetric
vault_password_file: "{{ ansible_facts['env'].HOME }}/password.txt"
- name: Remove file containing password from server.
ansible.builtin.file:
path: "{{ ansible_facts['env'].HOME }}/password.txt"
state: absent
ansible-freeipa-master/playbooks/vault/vault-is-present-with-public-key-file.yml 0000664 0000000 0000000 00000001640 14600563364 0030440 0 ustar 00root root 0000000 0000000 ---
#
# Example keys for this playbook were generated with the commands:
# $ openssl genrsa -out private.pem 2048
# $ openssl rsa -in private.pem -pubout > public.pem
#
- name: Tests
hosts: ipaserver
become: true
gather_facts: True
tasks:
- name: Copy public key file to server.
ansible.builtin.copy:
src: "{{ playbook_dir }}/public.pem"
dest: "{{ ansible_facts['env'].HOME }}/public.pem"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: 0600
- name: Ensure asymmetric vault exists with public key from file.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
username: admin
vault_type: asymmetric
vault_public_key_file: "{{ ansible_facts['env'].HOME }}/public.pem"
- name: Remove public key file from server.
ansible.builtin.file:
path: "{{ ansible_facts['env'].HOME }}/public.pem"
state: absent
ansible-freeipa-master/plugins/ 0000775 0000000 0000000 00000000000 14600563364 0017065 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/plugins/doc_fragments/ 0000775 0000000 0000000 00000000000 14600563364 0021700 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/plugins/doc_fragments/ipamodule_base_docs.py 0000664 0000000 0000000 00000003374 14600563364 0026242 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2021 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object): # pylint: disable=R0205,R0903
DOCUMENTATION = r"""
options:
ipaadmin_principal:
description: The admin principal.
default: admin
type: str
ipaadmin_password:
description: The admin password.
required: false
type: str
ipaapi_context:
description: |
The context in which the module will execute. Executing in a
server context is preferred. If not provided context will be
determined by the execution environment.
choices: ["server", "client"]
type: str
required: false
ipaapi_ldap_cache:
description: Use LDAP cache for IPA connection.
type: bool
default: true
"""
DELETE_CONTINUE = r"""
options:
delete_continue:
description: |
Continuous mode. Don't stop on errors. Valid only if `state` is `absent`.
aliases: ["continue"]
type: bool
default: True
"""
ansible-freeipa-master/plugins/module_utils/ 0000775 0000000 0000000 00000000000 14600563364 0021572 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/plugins/module_utils/ansible_freeipa_module.py 0000664 0000000 0000000 00000135204 14600563364 0026626 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Sergio Oliveira Campos
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__all__ = ["gssapi", "netaddr", "api", "ipalib_errors", "Env",
"DEFAULT_CONFIG", "LDAP_GENERALIZED_TIME_FORMAT",
"kinit_password", "kinit_keytab", "run", "DN", "VERSION",
"paths", "tasks", "get_credentials_if_valid", "Encoding",
"DNSName", "getargspec", "certificate_loader",
"write_certificate_list", "boolean", "template_str",
"urlparse"]
import os
# ansible-freeipa requires locale to be C, IPA requires utf-8.
os.environ["LANGUAGE"] = "C"
import sys
import operator
import tempfile
import shutil
import socket
import base64
import ast
from datetime import datetime
from contextlib import contextmanager
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils.common.text.converters import jsonify
from ansible.module_utils import six
from ansible.module_utils.common._collections_compat import Mapping
from ansible.module_utils.parsing.convert_bool import boolean
# Import getargspec from inspect or provide own getargspec for
# Python 2 compatibility with Python 3.11+.
try:
from inspect import getargspec
except ImportError:
from collections import namedtuple
from inspect import getfullargspec
# The code is copied from Python 3.10 inspect.py
# Authors: Ka-Ping Yee
# Yury Selivanov
ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults')
def getargspec(func):
args, varargs, varkw, defaults, kwonlyargs, _kwonlydefaults, \
ann = getfullargspec(func)
if kwonlyargs or ann:
raise ValueError(
"Function has keyword-only parameters or annotations"
", use inspect.signature() API which can support them")
return ArgSpec(args, varargs, varkw, defaults)
try:
import uuid
import netaddr
import gssapi
from ipalib import api
from ipalib import errors as ipalib_errors # noqa
from ipalib.config import Env
from ipalib.constants import DEFAULT_CONFIG, LDAP_GENERALIZED_TIME_FORMAT
try:
from ipalib.install.kinit import kinit_password, kinit_keytab
except ImportError:
from ipapython.ipautil import kinit_password, kinit_keytab
from ipapython.ipautil import run
from ipapython.ipautil import template_str
from ipapython.dn import DN
from ipapython.version import VERSION
from ipaplatform.paths import paths
from ipaplatform.tasks import tasks
from ipalib.krb_utils import get_credentials_if_valid
from ipapython.dnsutil import DNSName
from ipapython import kerberos
try:
from ipalib.x509 import Encoding
except ImportError:
from cryptography.hazmat.primitives.serialization import Encoding
try:
from ipalib.x509 import load_pem_x509_certificate
certificate_loader = load_pem_x509_certificate
except ImportError:
from ipalib.x509 import load_certificate
certificate_loader = load_certificate
from ipalib.x509 import write_certificate_list
# Try to import is_ipa_configured or use a fallback implementation.
try:
from ipalib.facts import is_ipa_configured
except ImportError:
try:
from ipaserver.install.installutils import is_ipa_configured
except ImportError:
from ipalib.install import sysrestore
def is_ipa_configured():
sstore = sysrestore.StateFile(paths.SYSRESTORE)
if sstore.has_state('installation'):
return sstore.get_state('installation', 'complete')
fstore = sysrestore.FileStore(paths.SYSRESTORE)
IPA_MODULES = [ # pylint: disable=invalid-name
'httpd', 'kadmin', 'dirsrv', 'pki-tomcatd', 'install',
'krb5kdc', 'ntpd', 'named'
]
for module in IPA_MODULES:
if sstore.has_state(module):
return True
return fstore.has_files()
# Try to import dcerpc
try:
import ipaserver.dcerpc # pylint: disable=no-member
_dcerpc_bindings_installed = True # pylint: disable=invalid-name
except ImportError:
_dcerpc_bindings_installed = False # pylint: disable=invalid-name
try:
from urllib.parse import urlparse
except ImportError:
from ansible.module_utils.six.moves.urllib.parse import urlparse
except ImportError as _err:
ANSIBLE_FREEIPA_MODULE_IMPORT_ERROR = str(_err)
for attr in __all__:
setattr(sys.modules[__name__], attr, None)
uuid = None
netaddr = None
is_ipa_configured = None
kerberos = None
ipaserver = None # pylint: disable=C0103
else:
ANSIBLE_FREEIPA_MODULE_IMPORT_ERROR = None
if six.PY3:
unicode = str
def valid_creds(module, principal): # noqa
"""Get valid credentials matching the princial, try GSSAPI first."""
if "KRB5CCNAME" in os.environ:
ccache = os.environ["KRB5CCNAME"]
module.debug('KRB5CCNAME set to %s' % ccache)
try:
cred = gssapi.Credentials(usage='initiate',
store={'ccache': ccache})
except gssapi.raw.misc.GSSError as e:
module.fail_json(msg='Failed to find default ccache: %s' % e)
else:
module.debug("Using principal %s" % str(cred.name))
return True
elif "KRB5_CLIENT_KTNAME" in os.environ:
keytab = os.environ.get('KRB5_CLIENT_KTNAME', None)
module.debug('KRB5_CLIENT_KTNAME set to %s' % keytab)
ccache_name = "MEMORY:%s" % str(uuid.uuid4())
os.environ["KRB5CCNAME"] = ccache_name
try:
cred = kinit_keytab(principal, keytab, ccache_name)
except gssapi.raw.misc.GSSError as e:
module.fail_json(msg='Kerberos authentication failed : %s' % e)
else:
module.debug("Using principal %s" % str(cred.name))
return True
creds = get_credentials_if_valid()
if creds and \
creds.lifetime > 0 and \
"%s@" % principal in creds.name.display_as(creds.name.name_type):
return True
return False
def temp_kinit(principal, password):
"""Kinit with password using a temporary ccache."""
if not password:
raise RuntimeError("The password is not set")
if not principal:
principal = "admin"
ccache_dir = tempfile.mkdtemp(prefix='krbcc')
ccache_name = os.path.join(ccache_dir, 'ccache')
try:
kinit_password(principal, password, ccache_name)
except RuntimeError as e:
raise RuntimeError("Kerberos authentication failed: %s" % str(e))
os.environ["KRB5CCNAME"] = ccache_name
return ccache_dir, ccache_name
def temp_kdestroy(ccache_dir, ccache_name):
"""Destroy temporary ticket and remove temporary ccache."""
if ccache_name is not None:
run([paths.KDESTROY, '-c', ccache_name], raiseonerr=False)
os.environ.pop('KRB5CCNAME', None)
if ccache_dir is not None:
shutil.rmtree(ccache_dir, ignore_errors=True)
def api_connect(context=None, **overrides):
"""
Initialize IPA API with the provided configuration.
Parameters
----------
context:
Set IPA API execution context. Valid values: "server", "client"
overrides:
Keyword argument dict containing arguments passed to
api.bootstrap() to configure API connection.
Valid overrides arguments include:
ldap_cache: Control use of LDAP cache layer. (bool)
"""
global _dcerpc_bindings_installed # pylint: disable=C0103,W0603
env = Env()
env._bootstrap()
env._finalize_core(**dict(DEFAULT_CONFIG))
# Fail connection if an unexpected argument is passed in 'overrides'.
_allowed = set(["ldap_cache"])
_inv = set(overrides.keys()) - _allowed
if _inv:
raise ValueError("Cannot override parameters: %s" % ",".join(_inv))
# If not set, context will be based on current API context.
if context is None:
context = "server" if is_ipa_configured() else "client"
# Available contexts are 'server' and 'client'.
if context not in ["server", "client"]:
raise ValueError("Invalid execution context: %s" % (context))
# IPA uses 'cli' for a 'client' context, but 'client'
# provides a better user interface. Here we map the
# value if needed.
if context == "client":
context = "cli"
api.bootstrap(context=context, debug=env.debug, log=None, **overrides)
api.finalize()
if api.env.in_server:
backend = api.Backend.ldap2
else:
backend = api.Backend.rpcclient
_dcerpc_bindings_installed = False
if not backend.isconnected():
backend.connect(ccache=os.environ.get('KRB5CCNAME', None))
def api_command(_module, command, name, args):
"""Call ipa.Command."""
return api.Command[command](name, **args)
def api_command_no_name(_module, command, args):
"""Call ipa.Command without a name."""
return api.Command[command](**args)
def api_check_command(command):
"""Return if command exists in command list."""
return command in api.Command
def api_check_param(command, name):
"""Check if param exists in command param list."""
return name in api.Command[command].params
def api_check_ipa_version(oper, requested_version):
"""
Compare the installed IPA version against a requested version.
The valid operators are: <, <=, >, >=, ==, !=
"""
oper_map = {
"<": operator.lt,
"<=": operator.le,
">": operator.gt,
">=": operator.ge,
"==": operator.eq,
"!=": operator.ne,
}
operation = oper_map.get(oper)
if not operation:
raise NotImplementedError("Invalid operator: %s" % oper)
return operation(tasks.parse_ipa_version(VERSION),
tasks.parse_ipa_version(requested_version))
def date_format(value):
accepted_date_formats = [
LDAP_GENERALIZED_TIME_FORMAT, # generalized time
'%Y-%m-%dT%H:%M:%SZ', # ISO 8601, second precision
'%Y-%m-%dT%H:%MZ', # ISO 8601, minute precision
'%Y-%m-%dZ', # ISO 8601, date only
'%Y-%m-%d %H:%M:%SZ', # non-ISO 8601, second precision
'%Y-%m-%d %H:%MZ', # non-ISO 8601, minute precision
]
for _date_format in accepted_date_formats:
try:
return datetime.strptime(value, _date_format)
except ValueError:
pass
raise ValueError("Invalid date '%s'" % value)
def compare_args_ipa(module, args, ipa, ignore=None): # noqa
"""Compare IPA object attributes against command arguments.
This function compares 'ipa' attributes with the 'args' the module
is intending to use as parameters to an IPA API command. A list of
attribute names that should be ignored during comparison may be
provided.
The comparison will be performed on every attribute provided in
'args'. If the attribute in 'args' or 'ipa' is not a scalar value
(including strings) the comparison will be performed as if the
attribute is a set of values, so duplicate values will count as a
single one. If both values are scalar values, then a direct
comparison is performed.
If an attribute is not available in 'ipa', its value is considered
to be a list with an empty string (['']), possibly forcing the
conversion of the 'args' attribute to a list for comparison. This
allows, for example, the usage of empty strings which should compare
as equals to inexistent attributes (None), as is done in IPA API.
This function is mostly useful to evaluate the need of a call to
IPA server when provided arguments are equivalent to the existing
values for a given IPA object.
Parameters
----------
module: AnsibleModule
The AnsibleModule used to log debug messages.
args: dict
The set of attributes provided by the playbook task.
ipa: dict
The set of attributes from the IPA object retrieved.
ignore: list
An optional list of attribute names that should be ignored and
not evaluated.
Return
------
True is returned if all attribute values in 'args' are
equivalent to the corresponding attribute value in 'ipa'.
"""
base_debug_msg = "Ansible arguments and IPA commands differed. "
# If both args and ipa are None, return there's no difference.
# If only one is None, return there is a difference.
# This tests avoid unecessary invalid access to attributes.
if args is None or ipa is None:
return args is None and ipa is None
# Fail if args or ipa are not dicts.
if not (isinstance(args, dict) and isinstance(ipa, dict)):
raise TypeError("Expected 'dicts' to compare.")
# Create filtered_args using ignore
if ignore is None:
ignore = []
filtered_args = [key for key in args if key not in ignore]
for key in filtered_args:
arg = args[key]
ipa_arg = ipa.get(key, [""])
# If ipa_arg is a list and arg is not, replace arg
# with list containing arg. Most args in a find result
# are lists, but not all.
if isinstance(ipa_arg, (list, tuple)):
if not isinstance(arg, list):
arg = [arg]
if len(ipa_arg) != len(arg):
module.debug(
base_debug_msg
+ "List length doesn't match for key %s: %d %d"
% (key, len(arg), len(ipa_arg),)
)
return False
# ensure list elements types are the same.
if not (
isinstance(ipa_arg[0], type(arg[0]))
or isinstance(arg[0], type(ipa_arg[0]))
):
arg = [to_text(_arg) for _arg in arg]
try:
arg_set = set(arg)
ipa_arg_set = set(ipa_arg)
except TypeError:
if arg != ipa_arg:
module.debug(
base_debug_msg
+ "Different values: %s %s" % (arg, ipa_arg)
)
return False
else:
if arg_set != ipa_arg_set:
module.debug(
base_debug_msg
+ "Different set content: %s %s"
% (arg_set, ipa_arg_set,)
)
return False
return True
def _afm_convert(value):
if value is not None:
if isinstance(value, list):
return [_afm_convert(x) for x in value]
if isinstance(value, dict):
return {_afm_convert(k): _afm_convert(v)
for k, v in value.items()}
if isinstance(value, str):
return to_text(value)
return value
def module_params_get(module, name, allow_empty_list_item=False):
value = _afm_convert(module.params.get(name))
# Fail on empty strings in the list or if allow_empty_list_item is True
# if there is another entry in the list together with the empty string.
# Due to an issue in Ansible it is possible to use the empty string
# "" for lists with choices, even if the empty list is not part of
# the choices.
# Ansible issue https://github.com/ansible/ansible/issues/77108
if isinstance(value, list):
for val in value:
if isinstance(val, (str, unicode)) and not val:
if not allow_empty_list_item:
module.fail_json(
msg="Parameter '%s' contains an empty string" %
name)
elif len(value) > 1:
module.fail_json(
msg="Parameter '%s' may not contain another "
"entry together with an empty string" % name)
return value
def module_params_get_lowercase(module, name, allow_empty_list_item=False):
value = module_params_get(module, name, allow_empty_list_item)
if isinstance(value, list):
value = [v.lower() for v in value]
if isinstance(value, (str, unicode)):
value = value.lower()
return value
def module_params_get_with_type_cast(
module, name, datatype, allow_empty=False
):
"""
Retrieve value set for module parameter as a specific data type.
Parameters
----------
module: AnsibleModule
The module from where to get the parameter value from.
name: string
The name of the parameter to retrieve.
datatype: type
The type to convert the value to, if value is not empty.
allow_empty: bool
Allow an empty string for non list parameters or a list
containing (only) an empty string item. This is used for
resetting parameters to the default value.
"""
value = module_params_get(module, name, allow_empty)
if not allow_empty and value == "":
module.fail_json(
msg="Argument '%s' must not be an empty string" % (name,)
)
if value is not None and value != "":
try:
if datatype is bool:
# We let Ansible handle bool values
value = boolean(value)
else:
value = datatype(value)
except ValueError:
module.fail_json(
msg="Invalid value '%s' for argument '%s'" % (value, name)
)
except TypeError as terr:
# If Ansible fails to parse a boolean, it will raise TypeError
module.fail_json(msg="Param '%s': %s" % (name, str(terr)))
return value
def api_get_domain():
return api.env.domain
def ensure_fqdn(name, domain):
if "." not in name:
return "%s.%s" % (name, domain)
return name
def api_get_realm():
return api.env.realm
def api_get_basedn():
return api.env.basedn
def gen_add_del_lists(user_list, res_list):
"""
Generate the lists for the addition and removal of members.
This function should be used to apply a new user list as a set
operation without action: members.
For the addition of new and the removal of existing members with
action: members gen_add_list and gen_intersection_list should
be used.
"""
# The user list is None, no need to do anything, return empty lists
if user_list is None:
return [], []
add_list = list(set(user_list or []) - set(res_list or []))
del_list = list(set(res_list or []) - set(user_list or []))
return add_list, del_list
def gen_add_list(user_list, res_list):
"""
Generate add list for addition of new members.
This function should be used to add new members with action: members
and state: present.
It is returning the difference of the user and res list if the user
list is not None.
"""
# The user list is None, no need to do anything, return empty list
if user_list is None:
return []
return list(set(user_list or []) - set(res_list or []))
def gen_intersection_list(user_list, res_list):
"""
Generate the intersection list for removal of existing members.
This function should be used to remove existing members with
action: members and state: absent.
It is returning the intersection of the user and res list if the
user list is not None.
"""
# The user list is None, no need to do anything, return empty list
if user_list is None:
return []
return list(set(res_list or []).intersection(set(user_list or [])))
def encode_certificate(cert):
"""
Encode a certificate using base64.
It also takes FreeIPA and Python versions into account.
"""
if isinstance(cert, (str, unicode, bytes)):
encoded = base64.b64encode(cert)
else:
encoded = base64.b64encode(cert.public_bytes(Encoding.DER))
if not six.PY2:
encoded = encoded.decode('ascii')
return encoded
def load_cert_from_str(cert):
cert = cert.strip()
if not cert.startswith("-----BEGIN CERTIFICATE-----"):
cert = "-----BEGIN CERTIFICATE-----\n" + cert
if not cert.endswith("-----END CERTIFICATE-----"):
cert += "\n-----END CERTIFICATE-----"
cert = certificate_loader(cert.encode('utf-8'))
return cert
def DN_x500_text(text): # pylint: disable=invalid-name
if hasattr(DN, "x500_text"):
return DN(text).x500_text()
# Emulate x500_text
dn = DN(text)
dn.rdns = reversed(dn.rdns)
return str(dn)
def is_valid_port(port):
if not isinstance(port, int):
return False
if 1 <= port <= 65535:
return True
return False
def is_ip_address(ipaddr):
"""Test if given IP address is a valid IPv4 or IPv6 address."""
try:
netaddr.IPAddress(str(ipaddr))
except (netaddr.AddrFormatError, ValueError):
return False
return True
def is_ip_network_address(ipaddr):
"""Test if given IP address is a valid IPv4 or IPv6 address."""
try:
netaddr.IPNetwork(str(ipaddr))
except (netaddr.AddrFormatError, ValueError):
return False
return True
def is_ipv4_addr(ipaddr):
"""Test if given IP address is a valid IPv4 address."""
try:
socket.inet_pton(socket.AF_INET, ipaddr)
except socket.error:
return False
return True
def is_ipv6_addr(ipaddr):
"""Test if given IP address is a valid IPv6 address."""
try:
socket.inet_pton(socket.AF_INET6, ipaddr)
except socket.error:
return False
return True
def servicedelegation_normalize_principals(module, principal,
check_exists=False):
"""
Normalize servicedelegation principals.
The principals can be service and with IPA 4.9.0+ also host principals.
"""
def _normalize_principal_name(name, realm):
# Normalize principal name
# Copied from ipaserver/plugins/servicedelegation.py
try:
princ = kerberos.Principal(name, realm=realm)
except ValueError as _err:
raise ipalib_errors.ValidationError(
name='principal',
reason="Malformed principal: %s" % str(_err))
if len(princ.components) == 1 and \
not princ.components[0].endswith('$'):
nprinc = 'host/' + unicode(princ)
else:
nprinc = unicode(princ)
return nprinc
def _check_exists(module, _type, name):
# Check if item of type _type exists using the show command
try:
module.ipa_command("%s_show" % _type, name, {})
except ipalib_errors.NotFound as e:
msg = str(e)
if "%s not found" % _type in msg:
return False
module.fail_json(msg="%s_show failed: %s" % (_type, msg))
return True
ipa_realm = module.ipa_get_realm()
_principal = []
for _princ in principal:
princ = _princ
realm = ipa_realm
# Get principal and realm from _princ if there is a realm
if '@' in _princ:
princ, realm = _princ.rsplit('@', 1)
# Lowercase principal
princ = princ.lower()
# Normalize principal
try:
nprinc = _normalize_principal_name(princ, realm)
except ipalib_errors.ValidationError as err:
module.fail_json(msg="%s: %s" % (_princ, str(err)))
princ = unicode(nprinc)
# Check that host principal exists
if princ.startswith("host/"):
if module.ipa_check_version("<", "4.9.0"):
module.fail_json(
msg="The use of host principals is not supported "
"by your IPA version")
# Get host FQDN (no leading 'host/' and no trailing realm)
# (There is no removeprefix and removesuffix in Python2)
_host = princ[5:]
if _host.endswith("@%s" % realm):
_host = _host[:-len(realm) - 1]
# Seach for host
if check_exists and not _check_exists(module, "host", _host):
module.fail_json(msg="Host '%s' does not exist" % _host)
# Check the service principal exists
else:
if check_exists and \
not _check_exists(module, "service", princ):
module.fail_json(msg="Service %s does not exist" % princ)
_principal.append(princ)
return _principal
def exit_raw_json(module, **kwargs):
"""
Print the raw parameters in JSON format, without masking.
Due to Ansible filtering out values in the output that match values
in variables which has `no_log` set, if a module need to return user
defined dato to the controller, it cannot rely on
AnsibleModule.exit_json, as there is a chance that a partial match may
occur, masking the data returned.
This method is a replacement for AnsibleModule.exit_json. It has
nearly the same implementation as exit_json, but does not filter
data. Beware that this data will be logged by Ansible, and if it
contains sensible data, it will be appear in the logs.
"""
module.do_cleanup_files()
print(jsonify(kwargs)) # pylint: disable=W0012,ansible-bad-function
sys.exit(0) # pylint: disable=W0012,ansible-bad-function
def __get_domain_validator():
if not _dcerpc_bindings_installed:
raise ipalib_errors.NotFound(
reason=(
'Cannot perform SID validation without Samba 4 support '
'installed. Make sure you have installed server-trust-ad '
'sub-package of IPA on the server'
)
)
# pylint: disable=no-member
domain_validator = ipaserver.dcerpc.DomainValidator(api)
# pylint: enable=no-member
if not domain_validator.is_configured():
raise ipalib_errors.NotFound(
reason=(
'Cross-realm trusts are not configured. Make sure you '
'have run ipa-adtrust-install on the IPA server first'
)
)
return domain_validator
def get_trusted_domain_sid_from_name(dom_name):
"""
Given a trust domain name, returns the domain SID.
Returns unicode string representation for a given trusted domain name
or None if SID for the given trusted domain name could not be found.
"""
domain_validator = __get_domain_validator()
sid = domain_validator.get_sid_from_domain_name(dom_name)
return unicode(sid) if sid is not None else None
class IPAParamMapping(Mapping):
"""
Provides IPA API mapping to playbook parameters or computed values.
It can be used to define a mapping of playbook parameters
or methods that provide computed values to IPA API arguments.
Playbook parameters can be retrieved as properties,
and the set of IPA arguments for a command can be
retrived with ``get_ipa_command_args()``. The keys for
``param_mapping`` are also the keys of the argument set.
The values of ``param_mapping`` can be either:
* a str representing a key of ``AnsibleModule.params``.
* a callable.
In case of an ``AnsibleModule.param`` the value of the playbook
param will be used for that argument. If it is a ``callable``,
the value returned by the execution of it will be used.
Example:
-------
def check_params(ipa_params):
# Module parameters can be accessed as properties.
if len(ipa_params.name) == 0:
ipa_params.ansible_module.fail_json(msg="No given name.")
def define_ipa_commands(self):
# Create the argument dict from the defined mapping.
args = self.get_ipa_command_args()
_commands = [("obj-name", "some_ipa_command", args)]
return _commands
def a_method_for_a_computed_param():
return "Some computed value"
def main():
ansible_module = SomeIPAModule(argument_spec=dict(
name=dict(type="list", aliases=["cn"], required=True),
state=dict(type="str", default="present",
choices=["present", "absent"]),
module_param=(type="str", required=False),
)
)
# Define the playbook to IPA API mapping
ipa_param_mapping = {
"arg_to_be_passed_to_ipa_command": "module_param",
"another_arg": a_method_for_a_computed_param,
}
ipa_params = IPAParamMapping(
ansible_module,
param_mapping=ipa_param_mapping
)
check_params(ipa_params)
comands = define_ipa_commands(ipa_params)
ansible_module.execute_ipa_commands(commands)
"""
def __init__(self, ansible_module, param_mapping=None):
self.mapping = ansible_module.params
self.ansible_module = ansible_module
self.param_mapping = param_mapping or {}
def __getitem__(self, key):
param = self.mapping[key]
if param is None:
return None
return _afm_convert(param)
def __iter__(self):
return iter(self.mapping)
def __len__(self):
return len(self.mapping)
@property
def names(self):
return self.name
def __getattr__(self, name):
return self.get(name)
def get_ipa_command_args(self, **kwargs):
"""Return a dict to be passed to an IPA command."""
args = {}
for ipa_param_name, param_name in self.param_mapping.items():
# Check if param_name is actually a param
if param_name in self.ansible_module.params:
value = self.ansible_module.params_get(param_name)
if (
self.ansible_module.ipa_check_version("<", "4.9.10")
and isinstance(value, bool)
):
value = "TRUE" if value else "FALSE"
# Since param wasn't a param check if it's a method name
elif callable(param_name):
value = param_name(**kwargs)
# We don't have a way to guess the value so fail.
else:
self.ansible_module.fail_json(
msg=(
"Couldn't get a value for '%s'. Option '%s' is "
"not a module argument neither a defined method."
)
% (ipa_param_name, param_name)
)
if value is not None:
args[ipa_param_name] = value
return args
class IPAAnsibleModule(AnsibleModule):
"""
IPA Ansible Module.
This class is an extended version of the Ansible Module that provides
IPA specific methods to simplify module generation.
Simple example:
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
name=dict(type="str", aliases=["cn"], default=None),
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
)
# Get parameters
name = ansible_module.params_get("name")
state = ansible_module.params_get("state")
# Connect to IPA API
with ansible_module.ipa_connect():
# Execute command
if state == "present":
ansible_module.ipa_command("command_add", name, {})
else:
ansible_module.ipa_command("command_del", name, {})
# Done
ansible_module.exit_json(changed=True)
if __name__ == "__main__":
main()
"""
# IPAAnsibleModule argument specs used for all modules
ipa_module_base_spec = dict(
ipaadmin_principal=dict(type="str", default="admin"),
ipaadmin_password=dict(type="str", required=False, no_log=True),
ipaapi_context=dict(
type="str", required=False, choices=["server", "client"],
),
ipaapi_ldap_cache=dict(type="bool", default="True"),
)
ipa_module_options_spec = dict(
delete_continue=dict(
type="bool", default=True, aliases=["continue"]
)
)
def __init__(self, *args, **kwargs):
# Extend argument_spec with ipa_module_base_spec
if "argument_spec" in kwargs:
_spec = kwargs["argument_spec"]
_spec.update(self.ipa_module_base_spec)
kwargs["argument_spec"] = _spec
if "ipa_module_options" in kwargs:
_update = {
k: self.ipa_module_options_spec[k]
for k in kwargs["ipa_module_options"]
}
_spec = kwargs.get("argument_spec", {})
_spec.update(_update)
kwargs["argument_spec"] = _spec
del kwargs["ipa_module_options"]
# pylint: disable=super-with-arguments
super(IPAAnsibleModule, self).__init__(*args, **kwargs)
if ANSIBLE_FREEIPA_MODULE_IMPORT_ERROR is not None:
self.fail_json(msg=ANSIBLE_FREEIPA_MODULE_IMPORT_ERROR)
@contextmanager
def ipa_connect(self, context=None):
"""
Create a context with a connection to IPA API.
Parameters
----------
context: string
An optional parameter defining which context API
commands will be executed.
"""
# ipaadmin vars
ipaadmin_principal = self.params_get("ipaadmin_principal")
ipaadmin_password = self.params_get("ipaadmin_password")
if context is None:
context = self.params_get("ipaapi_context")
# Get set of parameters to override in api.bootstrap().
# Here, all 'ipaapi_*' params are allowed, and the control
# of invalid parameters is delegated to api_connect.
_excl_override = ["ipaapi_context"]
overrides = {
name[len("ipaapi_"):]: self.params_get(name)
for name in self.params
if name.startswith("ipaapi_") and name not in _excl_override
}
ccache_dir = None
ccache_name = None
try:
if not valid_creds(self, ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(
ipaadmin_principal, ipaadmin_password)
api_connect(context, **overrides)
except Exception as e:
self.fail_json(msg=str(e))
else:
try:
yield ccache_name
except Exception as e:
self.fail_json(msg=str(e))
finally:
temp_kdestroy(ccache_dir, ccache_name)
def params_get(self, name, allow_empty_list_item=False):
"""
Retrieve value set for module parameter.
Parameters
----------
name: string
The name of the parameter to retrieve.
allow_empty_list_item: bool
The parameter allowes to have empty strings in a list
"""
return module_params_get(self, name, allow_empty_list_item)
def params_get_lowercase(self, name, allow_empty_list_item=False):
"""
Retrieve value set for module parameter as lowercase, if not None.
Parameters
----------
name: string
The name of the parameter to retrieve.
allow_empty_list_item: bool
The parameter allowes to have empty strings in a list
"""
return module_params_get_lowercase(self, name, allow_empty_list_item)
def params_get_with_type_cast(
self, name, datatype, allow_empty=True
):
"""
Retrieve value set for module parameter as a specific data type.
Parameters
----------
name: string
The name of the parameter to retrieve.
datatype: type
The type to convert the value to, if not empty.
datatype: type
The type to convert the value to, if value is not empty.
allow_empty: bool
Allow an empty string for non list parameters or a list
containing (only) an empty string item. This is used for
resetting parameters to the default value.
"""
return module_params_get_with_type_cast(
self, name, datatype, allow_empty)
def params_fail_used_invalid(self, invalid_params, state, action=None):
"""
Fail module execution if one of the invalid parameters is not None.
Parameters
----------
invalid_params:
List of parameters that must value 'None'.
state:
State being tested.
action:
Action being tested (optional).
"""
if action is None:
msg = "Argument '{0}' can not be used with state '{1}'"
else:
msg = "Argument '{0}' can not be used with action "\
"'{2}' and state '{1}'"
for param in invalid_params:
if self.params.get(param) is not None:
self.fail_json(msg=msg.format(param, state, action))
def ipa_command(self, command, name, args):
"""
Execute an IPA API command with a required `name` argument.
Parameters
----------
command: string
The IPA API command to execute.
name: string
The name parameter to pass to the command.
args: dict
The parameters to pass to the command.
"""
return api_command(self, command, name, args)
def ipa_command_no_name(self, command, args):
"""
Execute an IPA API command requiring no `name` argument.
Parameters
----------
command: string
The IPA API command to execute.
args: dict
The parameters to pass to the command.
"""
return api_command_no_name(self, command, args)
def ipa_get_domain(self):
"""Retrieve IPA API domain."""
if not hasattr(self, "__ipa_api_domain"):
setattr(self, "__ipa_api_domain", api_get_domain()) # noqa: B010
return getattr(self, "__ipa_api_domain") # noqa: B009
@staticmethod
def ipa_get_realm():
"""Retrieve IPA API realm."""
return api_get_realm()
@staticmethod
def ipa_get_basedn():
"""Retrieve IPA API basedn."""
return api_get_basedn()
@staticmethod
def ipa_command_exists(command):
"""
Check if IPA command is supported.
Parameters
----------
command: string
The IPA API command to verify.
"""
return api_check_command(command)
@staticmethod
def ipa_command_param_exists(command, name):
"""
Check if IPA command support a specific parameter.
Parameters
----------
command: string
The IPA API command to test.
name: string
The parameter name to verify.
"""
return api_check_param(command, name)
def ipa_command_invalid_param_choices(self, command, name, value):
"""
Return invalid parameter choices for IPA command.
Parameters
----------
command: string
The IPA API command to test.
name: string
The parameter name to check.
value: string
The parameter value to verify.
"""
if command not in api.Command:
self.fail_json(msg="The command '%s' does not exist." % command)
if name not in api.Command[command].params:
self.fail_json(msg="The command '%s' does not have a parameter "
"named '%s'." % (command, name))
if not hasattr(api.Command[command].params[name], "cli_metavar"):
self.fail_json(msg="The parameter '%s' of the command '%s' does "
"not have choices." % (name, command))
# For IPA 4.6 (RHEL-7):
# - krbprincipalauthind in host_add does not have choices defined
# - krbprincipalauthind in service_add does not have choices defined
#
# api.Command[command].params[name].cli_metavar returns "STR" and
# ast.literal_eval failes with a ValueError "malformed string".
#
# There is no way to verify that the given values are valid or not in
# this case. The check is done later on while applying the change
# with host_add, host_mod, service_add and service_mod.
try:
_choices = ast.literal_eval(
api.Command[command].params[name].cli_metavar)
except ValueError:
return None
return (set(value or []) - set([""])) - set(_choices)
@staticmethod
def ipa_check_version(oper, requested_version):
"""
Compare available IPA version.
Parameters
----------
oper: string
The relational operator to use.
requested_version: string
The version to compare to.
"""
return api_check_ipa_version(oper, requested_version)
# pylint: disable=unused-argument
@staticmethod
def member_error_handler(module, result, command, name, args, errors):
# Get all errors
for failed_item in result.get("failed", []):
failed = result["failed"][failed_item]
for member_type in failed:
for member, failure in failed[member_type]:
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
def execute_ipa_commands(self, commands, result_handler=None,
exception_handler=None,
fail_on_member_errors=False,
**handlers_user_args):
"""
Execute IPA API commands from command list.
Parameters
----------
commands: list of string tuple
The list of commands in the form (name, command and args)
For commands that do not require a 'name', None needs be
used.
result_handler: function
The user function to handle results of the single commands
exception_handler: function
The user function to handle exceptions of the single commands
Returns True to continue to next command, else False
fail_on_member_errors: bool
Use default member error handler handler member_error_handler
handlers_user_args: dict (user args mapping)
The user args to pass to result_handler and exception_handler
functions
Example (ipauser module):
def result_handler(module, result, command, name, args, exit_args,
one_name):
if "random" in args and command in ["user_add", "user_mod"] \
and "randompassword" in result["result"]:
if one_name:
exit_args["randompassword"] = \
result["result"]["randompassword"]
else:
exit_args.setdefault(name, {})["randompassword"] = \
result["result"]["randompassword"]
def exception_handler(module, ex, exit_args, one_name):
if ex.exception == ipalib_errors.EmptyModlist:
result = {}
return False
exit_args = {}
changed = module.execute_ipa_commands(commands, result_handler,
exception_handler,
exit_args=exit_args,
one_name=len(names)==1)
ansible_module.exit_json(changed=changed, user=exit_args)
"""
# Fail on given handlers_user_args without result or exception
# handler
if result_handler is None and exception_handler is None and \
len(handlers_user_args) > 0:
self.fail_json(msg="Args without result and exception hander: "
"%s" % repr(handlers_user_args))
# Fail on given result_handler and fail_on_member_errors
if result_handler is not None and fail_on_member_errors:
self.fail_json(
msg="result_handler given and fail_on_member_errors set")
# No commands, report no changes
if commands is None:
return False
# In check_mode return if there are commands to do
if self.check_mode:
return len(commands) > 0
# Error list for result_handler and error_handler
_errors = []
# Handle fail_on_member_errors, set result_handler to
# member_error_handler
# Add internal _errors for result_hendler if the module is not
# adding it. This also activates the final fail_json if
# errors are found.
if fail_on_member_errors:
result_handler = IPAAnsibleModule.member_error_handler
handlers_user_args["errors"] = _errors
elif result_handler is not None:
if "errors" not in handlers_user_args:
# pylint: disable=deprecated-method
argspec = getargspec(result_handler)
if "errors" in argspec.args:
handlers_user_args["errors"] = _errors
changed = False
for name, command, args in commands:
try:
if name is None:
result = self.ipa_command_no_name(command, args)
else:
result = self.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
# If result_handler is not None, call it with user args
# defined in **handlers_user_args
if result_handler is not None:
result_handler(self, result, command, name, args,
**handlers_user_args)
except Exception as e:
if exception_handler is not None and \
exception_handler(self, e, **handlers_user_args):
continue
self.fail_json(msg="%s: %s: %s" % (command, name, str(e)))
# Fail on errors from result_handler and exception_handler
if len(_errors) > 0:
self.fail_json(msg=", ".join(_errors))
return changed
ansible-freeipa-master/plugins/modules/ 0000775 0000000 0000000 00000000000 14600563364 0020535 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/plugins/modules/README.md 0000664 0000000 0000000 00000001047 14600563364 0022016 0 ustar 00root root 0000000 0000000 # Writing a new Ansible FreeIPA module
A ansible-freeipa module should have:
* Code:
* A module file placed in `plugins/modules/.py`
* Documentation:
* `README-.md` file in the root directory and linked from the main README.md
* Example playbooks in `playbooks//` directory
* Tests:
* Test cases (also playbooks) defined in `tests//test_.yml`. It's ok to have multiple files in this directory.
Use the script `utils/new_module` to create the stub files for a new module.
ansible-freeipa-master/plugins/modules/ipaautomember.py 0000664 0000000 0000000 00000053004 14600563364 0023743 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Mark Hahl
# Jake Reynolds
# Thomas Woerner
#
# Copyright (C) 2021-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaautomember
short_description: Add and delete FreeIPA Auto Membership Rules.
description: Add, modify and delete an IPA Auto Membership Rules.
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The automember rule
required: false
type: list
elements: str
aliases: ["cn"]
description:
description: A description of this auto member rule
required: false
type: str
automember_type:
description: Grouping to which the rule applies
required: false
type: str
choices: ["group", "hostgroup"]
exclusive:
description: List of dictionaries containing the attribute and expression.
type: list
elements: dict
aliases: ["automemberexclusiveregex"]
suboptions:
key:
description: The attribute of the regex
type: str
required: true
expression:
description: The expression of the regex
type: str
required: true
inclusive:
description: List of dictionaries containing the attribute and expression.
type: list
elements: dict
aliases: ["automemberinclusiveregex"]
suboptions:
key:
description: The attribute of the regex
type: str
required: true
expression:
description: The expression of the regex
type: str
required: true
users:
description: Users to rebuild membership for.
type: list
elements: str
required: false
hosts:
description: Hosts to rebuild membership for.
type: list
elements: str
required: false
no_wait:
description: Don't wait for rebuilding membership.
type: bool
default_group:
description: Default (fallback) group for all unmatched entries.
type: str
action:
description: Work on automember or member level
type: str
default: automember
choices: ["member", "automember"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent", "rebuilt", "orphans_removed"]
author:
- Mark Hahl (@mhahl)
- Jake Reynolds (@jake2184)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure an automember rule exists
- ipaautomember:
ipaadmin_password: SomeADMINpassword
name: admins
description: "example description"
automember_type: group
state: present
inclusive:
- key: "mail"
expression: "example.com"
# Delete an automember rule
- ipaautomember:
ipaadmin_password: SomeADMINpassword
name: admins
description: "my automember rule"
automember_type: group
state: absent
# Add an inclusive condition to an existing rule
- ipaautomember:
ipaadmin_password: SomeADMINpassword
name: "My domain hosts"
automember_type: hostgroup
action: member
inclusive:
- key: fqdn
expression: ".*.mydomain.com"
# Ensure group membership for all users has been rebuilt
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: group
state: rebuilt
# Ensure group membership for given users has been rebuilt
- ipaautomember:
ipaadmin_password: SomeADMINpassword
users:
- user1
- user2
state: rebuilt
# Ensure hostgroup membership for all hosts has been rebuilt
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: hostgroup
state: rebuilt
# Ensure hostgroup membership for given hosts has been rebuilt
- ipaautomember:
ipaadmin_password: SomeADMINpassword
hosts:
- host1.mydomain.com
- host2.mydomain.com
state: rebuilt
# Ensure default group fallback_group for all unmatched group entries is set
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: group
default_group: fallback_group
# Ensure default group for all unmatched group entries is not set
- ipaautomember:
ipaadmin_password: SomeADMINpassword
default_group: ""
automember_type: group
state: absent
# Ensure default hostgroup fallback_hostgroup for all unmatched group entries
# is set
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: hostgroup
default_group: fallback_hostgroup
# Ensure default hostgroup for all unmatched group entries is not set
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: hostgroup
default_group: ""
state: absent
# Example playbook to ensure all orphan automember group rules are removed:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: group
state: orphans_removed
# Example playbook to ensure all orphan automember hostgroup rules are removed:
- ipaautomember:
ipaadmin_password: SomeADMINpassword
automember_type: hostgroup
state: orphans_removed
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import (
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, ipalib_errors, DN
)
def find_automember(module, name, automember_type):
_args = {
"all": True,
"type": automember_type
}
try:
_result = module.ipa_command("automember_show", name, _args)
except ipalib_errors.NotFound:
return None
return _result["result"]
def find_automember_orphans(module, automember_type):
_args = {
"all": True,
"type": automember_type
}
try:
_result = module.ipa_command_no_name("automember_find_orphans", _args)
except ipalib_errors.NotFound:
return None
return _result
def find_automember_default_group(module, automember_type):
_args = {
"all": True,
"type": automember_type
}
try:
_result = module.ipa_command_no_name("automember_default_group_show",
_args)
except ipalib_errors.NotFound:
return None
return _result["result"]
def gen_condition_args(automember_type,
key,
inclusiveregex=None,
exclusiveregex=None):
_args = {}
if automember_type is not None:
_args['type'] = automember_type
if key is not None:
_args['key'] = key
if inclusiveregex is not None:
_args['automemberinclusiveregex'] = inclusiveregex
if exclusiveregex is not None:
_args['automemberexclusiveregex'] = exclusiveregex
return _args
def gen_rebuild_args(automember_type, rebuild_users, rebuild_hosts, no_wait):
_args = {"no_wait": no_wait}
if automember_type is not None:
_args['type'] = automember_type
if rebuild_users is not None:
_args["users"] = rebuild_users
if rebuild_hosts is not None:
_args["hosts"] = rebuild_hosts
return _args
def gen_args(description, automember_type):
_args = {}
if description is not None:
_args["description"] = description
if automember_type is not None:
_args['type'] = automember_type
return _args
def transform_conditions(conditions):
"""Transform a list of dicts into a list with the format of key=value."""
transformed = ['%s=%s' % (condition['key'], condition['expression'])
for condition in conditions]
return transformed
def check_condition_keys(ansible_module, conditions, aciattrs):
if conditions is None:
return
for condition in conditions:
if condition["key"] not in aciattrs:
ansible_module.fail_json(
msg="Invalid automember condition key '%s'" % condition["key"])
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
inclusive=dict(type="list",
aliases=["automemberinclusiveregex"],
default=None,
options=dict(
key=dict(type="str", required=True,
no_log=False),
expression=dict(type="str", required=True)
),
elements="dict",
required=False),
exclusive=dict(type="list",
aliases=["automemberexclusiveregex"],
default=None,
options=dict(
key=dict(type="str", required=True,
no_log=False),
expression=dict(type="str", required=True)
),
elements="dict",
required=False),
name=dict(type="list", elements="str", aliases=["cn"],
default=None, required=False),
description=dict(type="str", default=None),
automember_type=dict(type='str', required=False,
choices=['group', 'hostgroup']),
no_wait=dict(type="bool", default=None),
default_group=dict(type="str", default=None),
action=dict(type="str", default="automember",
choices=["member", "automember"]),
state=dict(type="str", default="present",
choices=["present", "absent", "rebuilt",
"orphans_removed"]),
users=dict(type="list", elements="str", default=None),
hosts=dict(type="list", elements="str", default=None),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
if names is None:
names = []
# present
description = ansible_module.params_get("description")
# conditions
inclusive = ansible_module.params_get("inclusive")
exclusive = ansible_module.params_get("exclusive")
# no_wait for rebuilt
no_wait = ansible_module.params_get("no_wait")
# default_group
default_group = ansible_module.params_get("default_group")
# action
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# grouping/type
automember_type = ansible_module.params_get("automember_type")
rebuild_users = ansible_module.params_get("users")
rebuild_hosts = ansible_module.params_get("hosts")
# Check parameters
invalid = []
if state in ["rebuilt", "orphans_removed"]:
invalid = ["name", "description", "exclusive", "inclusive",
"default_group"]
if action == "member":
ansible_module.fail_json(
msg="'action=member' is not usable with state '%s'" % state)
if state == "rebuilt":
if automember_type == "group" and rebuild_hosts is not None:
ansible_module.fail_json(
msg="state %s: hosts can not be set when type is '%s'" %
(state, automember_type))
if automember_type == "hostgroup" and rebuild_users is not None:
ansible_module.fail_json(
msg="state %s: users can not be set when type is '%s'" %
(state, automember_type))
elif state == "orphans_removed":
invalid.extend(["users", "hosts"])
if not automember_type:
ansible_module.fail_json(
msg="'automember_type' is required unless state: rebuilt")
else:
if default_group is not None:
for param in ["name", "exclusive", "inclusive", "users", "hosts"
"no_wait"]:
if ansible_module.params.get(param) is not None:
msg = "Cannot use {0} together with default_group"
ansible_module.fail_json(msg=msg.format(param))
if action == "member":
ansible_module.fail_json(
msg="Cannot use default_group with action:member")
if state == "absent":
ansible_module.fail_json(
msg="Cannot use default_group with state:absent")
else:
invalid = ["users", "hosts", "no_wait"]
if not automember_type:
ansible_module.fail_json(
msg="'automember_type' is required.")
ansible_module.params_fail_used_invalid(invalid, state, action)
# Init
changed = False
exit_args = {}
res_find = None
with ansible_module.ipa_connect():
commands = []
for name in names:
# Make sure automember rule exists
res_find = find_automember(ansible_module, name, automember_type)
# Check inclusive and exclusive conditions
if inclusive is not None or exclusive is not None:
# automember_type is either "group" or "hostgorup"
if automember_type == "group":
_type = u"user"
elif automember_type == "hostgroup":
_type = u"host"
else:
ansible_module.fail_json(
msg="Bad automember type '%s'" % automember_type)
try:
aciattrs = ansible_module.ipa_command(
"json_metadata", _type, {}
)['objects'][_type]['aciattrs']
except Exception as ex:
ansible_module.fail_json(
msg="%s: %s: %s" % ("json_metadata", _type, str(ex)))
check_condition_keys(ansible_module, inclusive, aciattrs)
check_condition_keys(ansible_module, exclusive, aciattrs)
# Create command
if state == 'present':
args = gen_args(description, automember_type)
if action == "automember":
if res_find is not None:
if not compare_args_ipa(ansible_module,
args,
res_find,
ignore=['type']):
commands.append([name, 'automember_mod', args])
else:
commands.append([name, 'automember_add', args])
res_find = {}
if inclusive is not None:
inclusive_add, inclusive_del = gen_add_del_lists(
transform_conditions(inclusive),
res_find.get("automemberinclusiveregex", [])
)
else:
inclusive_add, inclusive_del = [], []
if exclusive is not None:
exclusive_add, exclusive_del = gen_add_del_lists(
transform_conditions(exclusive),
res_find.get("automemberexclusiveregex", [])
)
else:
exclusive_add, exclusive_del = [], []
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No automember '%s'" % name)
inclusive_add = transform_conditions(inclusive or [])
inclusive_del = []
exclusive_add = transform_conditions(exclusive or [])
exclusive_del = []
for _inclusive in inclusive_add:
key, regex = _inclusive.split("=", 1)
condition_args = gen_condition_args(
automember_type, key, inclusiveregex=regex)
commands.append([name, 'automember_add_condition',
condition_args])
for _inclusive in inclusive_del:
key, regex = _inclusive.split("=", 1)
condition_args = gen_condition_args(
automember_type, key, inclusiveregex=regex)
commands.append([name, 'automember_remove_condition',
condition_args])
for _exclusive in exclusive_add:
key, regex = _exclusive.split("=", 1)
condition_args = gen_condition_args(
automember_type, key, exclusiveregex=regex)
commands.append([name, 'automember_add_condition',
condition_args])
for _exclusive in exclusive_del:
key, regex = _exclusive.split("=", 1)
condition_args = gen_condition_args(
automember_type, key, exclusiveregex=regex)
commands.append([name, 'automember_remove_condition',
condition_args])
elif state == 'absent':
if action == "automember":
if res_find is not None:
commands.append([name, 'automember_del',
{'type': automember_type}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No automember '%s'" % name)
if inclusive is not None:
for _inclusive in transform_conditions(inclusive):
key, regex = _inclusive.split("=", 1)
condition_args = gen_condition_args(
automember_type, key, inclusiveregex=regex)
commands.append(
[name, 'automember_remove_condition',
condition_args])
if exclusive is not None:
for _exclusive in transform_conditions(exclusive):
key, regex = _exclusive.split("=", 1)
condition_args = gen_condition_args(
automember_type, key, exclusiveregex=regex)
commands.append([name,
'automember_remove_condition',
condition_args])
if len(names) == 0:
if state == "rebuilt":
args = gen_rebuild_args(automember_type, rebuild_users,
rebuild_hosts, no_wait)
commands.append([None, 'automember_rebuild', args])
elif state == "orphans_removed":
res_find = find_automember_orphans(ansible_module,
automember_type)
if res_find["count"] > 0:
commands.append([None, 'automember_find_orphans',
{'type': automember_type,
'remove': True}])
elif default_group is not None and state == "present":
res_find = find_automember_default_group(ansible_module,
automember_type)
if default_group == "":
if isinstance(res_find["automemberdefaultgroup"], list):
commands.append([None,
'automember_default_group_remove',
{'type': automember_type}])
else:
dn_default_group = [DN(('cn', default_group),
('cn', '%ss' % automember_type),
('cn', 'accounts'),
ansible_module.ipa_get_basedn())]
if repr(res_find["automemberdefaultgroup"]) != \
repr(dn_default_group):
commands.append(
[None, 'automember_default_group_set',
{'type': automember_type,
'automemberdefaultgroup': default_group}])
else:
ansible_module.fail_json(msg="Invalid operation")
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# result["failed"] is used only for INCLUDE_RE, EXCLUDE_RE
# if entries could not be added that are already there and
# if entries could not be removed that are not there.
# All other issues like invalid attributes etc. are handled
# as exceptions. Therefore the error section is not here as
# in other modules.
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaautomountkey.py 0000664 0000000 0000000 00000016000 14600563364 0024342 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Chris Procter
# Thomas Woerner
#
# Copyright (C) 2021-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = '''
---
module: ipaautomountkey
author:
- Chris Procter (@chr15p))
- Thomas Woerner (@t-woerner)
short_description: Manage FreeIPA autommount map
description:
- Add, delete, and modify an IPA automount map
extends_documentation_fragment:
- ipamodule_base_docs
options:
location:
description: automount location map is in
type: str
required: True
aliases: ["automountlocationcn", "automountlocation"]
mapname:
description: automount map to be managed
type: str
aliases: ["map", "automountmapname", "automountmap"]
required: True
key:
description: automount key to be managed
type: str
required: True
aliases: ["name", "automountkey"]
rename:
description: key to change to if state is 'renamed'
type: str
required: False
aliases: ["new_name", "newautomountkey"]
info:
description: Mount information for the key
type: str
required: False
aliases: ["information", "automountinformation"]
state:
description: State to ensure
type: str
required: False
default: present
choices: ["present", "absent", "renamed"]
'''
EXAMPLES = '''
- name: create key TestKey
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
locationcn: TestLocation
mapname: TestMap
key: TestKey
info: 192.168.122.1:/exports
state: present
- name: ensure key TestKey is absent
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
mapname: TestMap
key: TestKey
state: absent
'''
RETURN = '''
'''
from ansible.module_utils.ansible_freeipa_module import (
IPAAnsibleModule, ipalib_errors
)
class AutomountKey(IPAAnsibleModule):
def __init__(self, *args, **kwargs):
# pylint: disable=super-with-arguments
super(AutomountKey, self).__init__(*args, **kwargs)
self.commands = []
def get_key(self, location, mapname, key):
try:
args = {
"automountmapautomountmapname": mapname,
"automountkey": key,
"all": True,
}
resp = self.ipa_command("automountkey_show", location, args)
except ipalib_errors.NotFound:
return None
return resp.get("result")
def check_ipa_params(self):
invalid = []
state = self.params_get("state")
if state == "present":
invalid = ["rename"]
if not self.params_get("info"):
self.fail_json(msg="Value required for argument 'info'")
if state == "rename":
invalid = ["info"]
if not self.params_get("rename"):
self.fail_json(msg="Value required for argument 'renamed'")
if state == "absent":
invalid = ["info", "rename"]
self.params_fail_used_invalid(invalid, state)
@staticmethod
def get_args(mapname, key, info, rename):
_args = {}
if mapname:
_args["automountmapautomountmapname"] = mapname
if key:
_args["automountkey"] = key
if info:
_args["automountinformation"] = info
if rename:
_args["rename"] = rename
return _args
def define_ipa_commands(self):
state = self.params_get("state")
location = self.params_get("location")
mapname = self.params_get("mapname")
key = self.params_get("key")
info = self.params_get("info")
rename = self.params_get("rename")
args = self.get_args(mapname, key, info, rename)
res_find = self.get_key(location, mapname, key)
if state == "present":
if res_find is None:
# does not exist and is wanted
self.commands.append([location, "automountkey_add", args])
else:
# exists and is wanted, check for changes
if info not in res_find.get("automountinformation"):
self.commands.append([location, "automountkey_mod", args])
if state == "renamed":
if res_find is None:
self.fail_json(
msg=(
"Cannot rename inexistent key: '%s', '%s', '%s'"
% (location, mapname, key)
)
)
self.commands.append([location, "automountkey_mod", args])
if state == "absent":
# if key exists and self.ipa_params.state == "absent":
if res_find is not None:
self.commands.append([location, "automountkey_del", args])
def main():
ipa_module = AutomountKey(
argument_spec=dict(
state=dict(
type='str',
choices=['present', 'absent', 'renamed'],
required=False,
default='present',
),
location=dict(
type="str",
aliases=["automountlocationcn", "automountlocation"],
required=True,
),
rename=dict(
type="str",
aliases=["new_name", "newautomountkey"],
required=False,
),
mapname=dict(
type="str",
aliases=["map", "automountmapname", "automountmap"],
required=True,
),
key=dict(
type="str",
aliases=["name", "automountkey"],
required=True,
no_log=False,
),
info=dict(
type="str",
aliases=["information", "automountinformation"],
required=False,
),
),
)
ipaapi_context = ipa_module.params_get("ipaapi_context")
with ipa_module.ipa_connect(context=ipaapi_context):
ipa_module.check_ipa_params()
ipa_module.define_ipa_commands()
changed = ipa_module.execute_ipa_commands(ipa_module.commands)
ipa_module.exit_json(changed=changed)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaautomountlocation.py 0000664 0000000 0000000 00000007766 14600563364 0025405 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Chris Procter
# Thomas Woerner
#
# Copyright (C) 2021-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = '''
---
module: ipaautomountlocation
author:
- Chris Procter (@chr15p)
- Thomas Woerner (@t-woerner)
short_description: Manage FreeIPA autommount locations
description:
- Add and delete an IPA automount location
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The automount location to be managed
required: true
type: list
elements: str
aliases: ["cn","location"]
state:
description: State to ensure
required: false
type: str
default: present
choices: ["present", "absent"]
'''
EXAMPLES = '''
- name: ensure a automount location named DMZ exists
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: DMZ
state: present
- name: ensure a automount location named DMZ is absent
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: DMZ
state: absent
'''
RETURN = '''
'''
from ansible.module_utils.ansible_freeipa_module import (
IPAAnsibleModule, ipalib_errors
)
class AutomountLocation(IPAAnsibleModule):
def __init__(self, *args, **kwargs):
# pylint: disable=super-with-arguments
super(AutomountLocation, self).__init__(*args, **kwargs)
self.commands = []
def get_location(self, location):
try:
response = self.ipa_command(
"automountlocation_show", location, {}
)
except ipalib_errors.NotFound:
return None
return response.get("result", None)
def check_ipa_params(self):
if len(self.params_get("name")) == 0:
self.fail_json(msg="At least one location must be provided.")
def define_ipa_commands(self):
state = self.params_get("state")
for location_name in self.params_get("name"):
location = self.get_location(location_name)
if not location and state == "present":
# does not exist and is wanted
self.commands.append(
(location_name, "automountlocation_add", {}))
elif location and state == "absent":
# exists and is not wanted
self.commands.append(
(location_name, "automountlocation_del", {}))
def main():
ipa_module = AutomountLocation(
argument_spec=dict(
state=dict(type='str',
default='present',
choices=['present', 'absent']
),
name=dict(type="list", elements="str",
aliases=["cn", "location"],
required=True
),
),
)
ipaapi_context = ipa_module.params_get("ipaapi_context")
with ipa_module.ipa_connect(context=ipaapi_context):
ipa_module.check_ipa_params()
ipa_module.define_ipa_commands()
changed = ipa_module.execute_ipa_commands(ipa_module.commands)
ipa_module.exit_json(changed=changed)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaautomountmap.py 0000664 0000000 0000000 00000027121 14600563364 0024335 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Chris Procter
# Thomas Woerner
#
# Copyright (C) 2021-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = '''
---
module: ipaautomountmap
author:
- Chris Procter (@chr15p)
- Thomas Woerner (@t-woerner)
- Rafael Jeffman (@rjeffman)
short_description: Manage FreeIPA autommount map
description:
- Add, delete, and modify an IPA automount map
extends_documentation_fragment:
- ipamodule_base_docs
options:
automountlocation:
description: automount location map is anchored to
type: str
aliases: ["location", "automountlocationcn"]
required: True
name:
description: automount map to be managed.
type: list
elements: str
aliases: ["mapname", "map", "automountmapname"]
required: True
desc:
description: description of automount map.
type: str
aliases: ["description"]
required: false
parentmap:
description: |
Parent map of the indirect map. Can only be used when creating
new maps.
type: str
required: false
mount:
description: Indirect map mount point, relative to parent map.
type: str
required: false
state:
description: State to ensure
type: str
required: false
default: present
choices: ["present", "absent"]
'''
EXAMPLES = '''
- name: ensure map named auto.DMZ in location DMZ is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: auto.DMZ
location: DMZ
desc: "this is a map for servers in the DMZ"
- name: ensure indirect map exists
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: auto.INDIRECT
location: DMZ
parentmap: auto.DMZ
mount: indirect
- name: remove a map named auto.DMZ in location DMZ if it exists
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: auto.DMZ
location: DMZ
state: absent
'''
RETURN = '''
'''
from ansible.module_utils.ansible_freeipa_module import (
IPAAnsibleModule, compare_args_ipa
)
class AutomountMap(IPAAnsibleModule):
def __init__(self, *args, **kwargs):
# pylint: disable=super-with-arguments
super(AutomountMap, self).__init__(*args, **kwargs)
self.commands = []
def get_automountmap(self, location, name):
try:
response = self.ipa_command(
"automountmap_show",
location,
{"automountmapname": name, "all": True}
)
except Exception: # pylint: disable=broad-except
return None
return response["result"]
def get_indirect_map_keys(self, location, name):
"""Check if 'name' is an indirect map for 'parentmap'."""
try:
maps = self.ipa_command("automountmap_find", location, {})
except Exception: # pylint: disable=broad-except
return []
result = []
for check_map in maps.get("result", []):
_mapname = check_map['automountmapname'][0]
keys = self.ipa_command(
"automountkey_find",
location,
{
"automountmapautomountmapname": _mapname,
"all": True
}
)
cmp_value = (
name if _mapname == "auto.master" else "ldap:{0}".format(name)
)
result.extend([
(location, _mapname, key.get("automountkey")[0])
for key in keys.get("result", [])
for mount_info in key.get("automountinformation", [])
if cmp_value in mount_info
])
return result
def check_ipa_params(self):
invalid = []
name = self.params_get("name")
state = self.params_get("state")
if state == "present":
if len(name) != 1:
self.fail_json(msg="Exactly one name must be provided for"
" 'state: present'.")
mount = self.params_get("mount") or False
parentmap = self.params_get("parentmap")
if parentmap:
if not mount:
self.fail_json(
msg="Must provide 'mount' parameter for indirect map."
)
elif parentmap != "auto.master" and mount[0] == "/":
self.fail_json(
msg="mount point is relative to parent map, "
"cannot begin with '/'"
)
if state == "absent":
if len(name) == 0:
self.fail_json(msg="At least one 'name' must be provided for"
" 'state: absent'")
invalid = ["desc", "parentmap", "mount"]
self.params_fail_used_invalid(invalid, state)
def get_args(self, mapname, desc, parentmap, mount):
# automountmapname is required for all automountmap operations.
if not mapname:
self.fail_json(msg="automountmapname cannot be None or empty.")
_args = {"automountmapname": mapname}
# An empty string is valid and will clear the attribute.
if desc is not None:
_args["description"] = desc
# indirect map attributes
if parentmap is not None:
_args["parentmap"] = parentmap
if mount is not None:
_args["key"] = mount
return _args
def define_ipa_commands(self):
name = self.params_get("name")
state = self.params_get("state")
location = self.params_get("location")
desc = self.params_get("desc")
mount = self.params_get("mount")
parentmap = self.params_get("parentmap")
for mapname in name:
automountmap = self.get_automountmap(location, mapname)
is_indirect_map = any([parentmap, mount])
if state == "present":
args = self.get_args(mapname, desc, parentmap, mount)
if automountmap is None:
if is_indirect_map:
if (
parentmap and
self.get_automountmap(location, parentmap) is None
):
self.fail_json(msg="Parent map does not exist.")
self.commands.append(
[location, "automountmap_add_indirect", args]
)
else:
self.commands.append(
[location, "automountmap_add", args]
)
else:
has_changes = not compare_args_ipa(
self, args, automountmap, ['parentmap', 'key']
)
if is_indirect_map:
map_config = (
location, parentmap or "auto.master", mount
)
indirects = self.get_indirect_map_keys(
location, mapname
)
if map_config not in indirects or has_changes:
self.fail_json(
msg="Indirect maps can only be created, "
"not modified."
)
elif has_changes:
self.commands.append(
[location, "automountmap_mod", args]
)
elif state == "absent":
def find_keys(parent_loc, parent_map, parent_key):
return self.ipa_command(
"automountkey_show",
parent_loc,
{
"automountmapautomountmapname": parent_map,
"automountkey": parent_key,
}
).get("result")
if automountmap is not None:
indirects = self.get_indirect_map_keys(location, mapname)
# Remove indirect map configurations for this map
self.commands.extend([
(
ploc,
"automountkey_del",
{
"automountmapautomountmapname": pmap,
"automountkey": pkey,
}
)
for ploc, pmap, pkey in indirects
if find_keys(ploc, pmap, pkey)
])
# Remove map
self.commands.append([
location,
"automountmap_del",
{"automountmapname": [mapname]}
])
# ensure commands are unique and automountkey commands are
# executed first in the list
def hashable_dict(dictionaire):
return tuple(
(k, tuple(v) if isinstance(v, (list, tuple)) else v)
for k, v in dictionaire.items()
)
cmds = [
(name, cmd, hashable_dict(args))
for name, cmd, args in self.commands
]
self.commands = [
(name, cmd, dict(args))
for name, cmd, args in
sorted(set(cmds), key=lambda cmd: cmd[1])
]
def main():
ipa_module = AutomountMap(
argument_spec=dict(
state=dict(type='str',
default='present',
choices=['present', 'absent']
),
location=dict(type="str",
aliases=["automountlocation", "automountlocationcn"],
required=True
),
name=dict(type="list", elements="str",
aliases=["mapname", "map", "automountmapname"],
required=True
),
desc=dict(type="str",
aliases=["description"],
required=False,
default=None
),
parentmap=dict(
type="str", required=False, default=None
),
mount=dict(type="str", required=False, default=None),
),
)
changed = False
ipaapi_context = ipa_module.params_get("ipaapi_context")
with ipa_module.ipa_connect(context=ipaapi_context):
ipa_module.check_ipa_params()
ipa_module.define_ipa_commands()
changed = ipa_module.execute_ipa_commands(ipa_module.commands)
ipa_module.exit_json(changed=changed)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipacert.py 0000664 0000000 0000000 00000042632 14600563364 0022545 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Sam Morris
# Rafael Guterres Jeffman
#
# Copyright (C) 2021 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipacert
short description: Manage FreeIPA certificates
description: Manage FreeIPA certificates
extends_documentation_fragment:
- ipamodule_base_docs
options:
csr:
description: |
X509 certificate signing request, in RFC 7468 PEM encoding.
Only available if `state: requested`, required if `csr_file` is not
provided.
type: str
csr_file:
description: |
Path to file with X509 certificate signing request, in RFC 7468 PEM
encoding. Only available if `state: requested`, required if `csr_file`
is not provided.
type: str
principal:
description: |
Host/service/user principal for the certificate.
Required if `state: requested`. Only available if `state: requested`.
type: str
add:
description: |
Automatically add the principal if it doesn't exist (service
principals only). Only available if `state: requested`.
type: bool
aliases: ["add_principal"]
required: false
ca:
description: Name of the issuing certificate authority.
type: str
required: false
serial_number:
description: |
Certificate serial number. Cannot be used with `state: requested`.
Required for all states, except `requested`.
type: int
profile:
description: Certificate Profile to use.
type: str
aliases: ["profile_id"]
required: false
revocation_reason:
description: |
Reason for revoking the certificate. Use one of the reason strings,
or the corresponding value: "unspecified" (0), "keyCompromise" (1),
"cACompromise" (2), "affiliationChanged" (3), "superseded" (4),
"cessationOfOperation" (5), "certificateHold" (6), "removeFromCRL" (8),
"privilegeWithdrawn" (9), "aACompromise" (10).
Use only if `state: revoked`. Required if `state: revoked`.
type: raw
aliases: ['reason']
certificate_out:
description: |
Write certificate (chain if `chain` is set) to this file, on the target
node.. Use only when `state` is `requested` or `retrieved`.
type: str
required: false
state:
description: |
The state to ensure. `held` is the same as revoke with reason
"certificateHold" (6). `released` is the same as `cert-revoke-hold`
on IPA CLI, releasing the hold status of a certificate.
choices: ["requested", "held", "released", "revoked", "retrieved"]
required: true
type: str
author:
authors:
- Sam Morris (@yrro)
- Rafael Guterres Jeffman (@rjeffman)
"""
EXAMPLES = """
- name: Request a certificate for a web server
ipacert:
ipaadmin_password: SomeADMINpassword
state: requested
csr: |
-----BEGIN CERTIFICATE REQUEST-----
MIGYMEwCAQAwGTEXMBUGA1UEAwwOZnJlZWlwYSBydWxlcyEwKjAFBgMrZXADIQBs
HlqIr4b/XNK+K8QLJKIzfvuNK0buBhLz3LAzY7QDEqAAMAUGAytlcANBAF4oSCbA
5aIPukCidnZJdr491G4LBE+URecYXsPknwYb+V+ONnf5ycZHyaFv+jkUBFGFeDgU
SYaXm/gF8cDYjQI=
-----END CERTIFICATE REQUEST-----
principal: HTTP/www.example.com
register: cert
- name: Request certificate for a user, with an appropriate profile.
ipacert:
ipaadmin_password: SomeADMINpassword
csr: |
-----BEGIN CERTIFICATE REQUEST-----
MIIBejCB5AIBADAQMQ4wDAYDVQQDDAVwaW5reTCBnzANBgkqhkiG9w0BAQEFAAOB
jQAwgYkCgYEA7uChccy1Is1FTM0SF23WPYW472E3ozeLh2kzhKR9Ni6FLmeEGgu7
/hicR1VwvXHYkNwI1tpW9LqxRVvgr6vheqHySljrBcoRfshfYvKejp03l2327Bfq
BNxXqLcHylNEyg8SH0u63bWyxtgoDBfdZwdGAhYuJ+g4ev79J5eYoB0CAwEAAaAr
MCkGCSqGSIb3DQEJDjEcMBowGAYHKoZIzlYIAQQNDAtoZWxsbyB3b3JsZDANBgkq
hkiG9w0BAQsFAAOBgQADCi5BHDv1mrBFDWqYytFpQ1mrvr/mdax3AYXxNL2UEV8j
AqZAFTEnJXL/u1eVQtI1yotqxakyUBN4XZBP2CBgJRO93Mtry8cgvU1sPdU8Mavx
5gSnlP74Hio2ziscWWydlxpYxFx0gkKvu+0nyIpz954SVYwQ2wwk5FRqZnxI5w==
-----END CERTIFICATE REQUEST-----
principal: pinky
profile_id: IECUserRoles
state: requested
- name: Temporarily hold a certificate
ipacert:
ipaadmin_password: SomeADMINpassword
serial_number: 12345
state: held
- name: Remove a certificate hold
ipacert:
ipaadmin_password: SomeADMINpassword
state: released
serial_number: 12345
- name: Permanently revoke a certificate issued by a lightweight sub-CA
ipacert:
ipaadmin_password: SomeADMINpassword
state: revoked
ca: vpn-ca
serial_number: 0x98765
reason: keyCompromise
- name: Retrieve a certificate
ipacert:
ipaadmin_password: SomeADMINpassword
serial_number: 12345
state: retrieved
register: cert_retrieved
"""
RETURN = """
certificate:
description: Certificate fields and data.
returned: |
if `state` is `requested` or `retrived` and `certificate_out`
is not defined.
type: dict
contains:
certificate:
description: |
Issued X509 certificate in PEM encoding. Will include certificate
chain if `chain: true` is used.
type: list
elements: str
returned: always
issuer:
description: X509 distinguished name of issuer.
type: str
sample: CN=Certificate Authority,O=EXAMPLE.COM
returned: always
serial_number:
description: Serial number of the issued certificate.
type: int
sample: 902156300
returned: always
valid_not_after:
description: |
Time when issued certificate ceases to be valid,
in GeneralizedTime format (YYYYMMDDHHMMSSZ).
type: str
returned: always
valid_not_before:
description: |
Time when issued certificate becomes valid, in
GeneralizedTime format (YYYYMMDDHHMMSSZ).
type: str
returned: always
subject:
description: X509 distinguished name of certificate subject.
type: str
sample: CN=www.example.com,O=EXAMPLE.COM
returned: always
san_dnsname:
description: X509 Subject Alternative Name.
type: list
elements: str
sample: ['www.example.com', 'other.example.com']
returned: |
when DNSNames are present in the Subject Alternative Name
extension of the issued certificate.
revoked:
description: Revoked status of the certificate.
type: bool
returned: always
owner_user:
description: The username that owns the certificate.
type: str
returned: when `state` is `retrieved`
owner_host:
description: The host that owns the certificate.
type: str
returned: when `state` is `retrieved`
owner_service:
description: The service that owns the certificate.
type: str
returned: when `state` is `retrieved`
"""
import base64
import time
import ssl
from ansible.module_utils import six
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import (
IPAAnsibleModule, certificate_loader, write_certificate_list,
)
if six.PY3:
unicode = str
# Reasons are defined in RFC 5280 sec. 5.3.1; removeFromCRL is not present in
# this list; run the module with state=released instead.
REVOCATION_REASONS = {
'unspecified': 0,
'keyCompromise': 1,
'cACompromise': 2,
'affiliationChanged': 3,
'superseded': 4,
'cessationOfOperation': 5,
'certificateHold': 6,
'removeFromCRL': 8,
'privilegeWithdrawn': 9,
'aACompromise': 10,
}
def gen_args(
module, principal=None, add_principal=None, ca=None, chain=None,
profile=None, certificate_out=None, reason=None
):
args = {}
if principal is not None:
args['principal'] = principal
if add_principal is not None:
args['add'] = add_principal
if ca is not None:
args['cacn'] = ca
if profile is not None:
args['profile_id'] = profile
if certificate_out is not None:
args['out'] = certificate_out
if chain:
args['chain'] = True
if ca:
args['cacn'] = ca
if reason is not None:
args['revocation_reason'] = get_revocation_reason(module, reason)
return args
def get_revocation_reason(module, reason):
"""Ensure revocation reasion is a valid integer code."""
reason_int = -1
try:
reason_int = int(reason)
except ValueError:
reason_int = REVOCATION_REASONS.get(reason, -1)
if reason_int not in REVOCATION_REASONS.values():
module.fail_json(msg="Invalid revocation reason: %s" % reason)
return reason_int
def parse_cert_timestamp(dt):
"""Ensure time is in GeneralizedTime format (YYYYMMDDHHMMSSZ)."""
return time.strftime(
"%Y%m%d%H%M%SZ",
time.strptime(dt, "%a %b %d %H:%M:%S %Y UTC")
)
def result_handler(_module, result, _command, _name, _args, exit_args, chain):
"""Split certificate into fields."""
if chain:
exit_args['certificate'] = [
ssl.DER_cert_to_PEM_cert(c)
for c in result['result'].get('certificate_chain', [])
]
else:
exit_args['certificate'] = [
ssl.DER_cert_to_PEM_cert(
base64.b64decode(result['result']['certificate'])
)
]
exit_args['san_dnsname'] = [
str(dnsname)
for dnsname in result['result'].get('san_dnsname', [])
]
exit_args.update({
key: result['result'][key]
for key in [
'issuer', 'subject', 'serial_number',
'revoked', 'revocation_reason'
]
if key in result['result']
})
exit_args.update({
key: result['result'][key][0]
for key in ['owner_user', 'owner_host', 'owner_service']
if key in result['result']
})
exit_args.update({
key: parse_cert_timestamp(result['result'][key])
for key in ['valid_not_after', 'valid_not_before']
if key in result['result']
})
def do_cert_request(
module, csr, principal, add_principal=None, ca=None, profile=None,
chain=None, certificate_out=None
):
"""Request a certificate."""
args = gen_args(
module, principal=principal, ca=ca, chain=chain,
add_principal=add_principal, profile=profile,
)
exit_args = {}
commands = [[to_text(csr), "cert_request", args]]
changed = module.execute_ipa_commands(
commands,
result_handler=result_handler,
exit_args=exit_args,
chain=chain
)
if certificate_out is not None:
certs = (
certificate_loader(cert.encode("utf-8"))
for cert in exit_args['certificate']
)
write_certificate_list(certs, certificate_out)
exit_args = {}
return changed, exit_args
def do_cert_revoke(ansible_module, serial_number, reason=None, ca=None):
"""Revoke a certificate."""
_ign, cert = do_cert_retrieve(ansible_module, serial_number, ca)
if not cert or cert.get('revoked', False):
return False, cert
args = gen_args(ansible_module, ca=ca, reason=reason)
commands = [[serial_number, "cert_revoke", args]]
changed = ansible_module.execute_ipa_commands(commands)
return changed, cert
def do_cert_release(ansible_module, serial_number, ca=None):
"""Release hold on certificate."""
_ign, cert = do_cert_retrieve(ansible_module, serial_number, ca)
revoked = cert.get('revoked', True)
reason = cert.get('revocation_reason', -1)
if cert and not revoked:
return False, cert
if revoked and reason != 6: # can only release held certificates
ansible_module.fail_json(
msg="Cannot release hold on certificate revoked with"
" reason: %d" % reason
)
args = gen_args(ansible_module, ca=ca)
commands = [[serial_number, "cert_remove_hold", args]]
changed = ansible_module.execute_ipa_commands(commands)
return changed, cert
def do_cert_retrieve(
module, serial_number, ca=None, chain=None, outfile=None
):
"""Retrieve a certificate with 'cert-show'."""
args = gen_args(module, ca=ca, chain=chain, certificate_out=outfile)
exit_args = {}
commands = [[serial_number, "cert_show", args]]
module.execute_ipa_commands(
commands,
result_handler=result_handler,
exit_args=exit_args,
chain=chain,
)
if outfile is not None:
exit_args = {}
return False, exit_args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# requested
csr=dict(type="str"),
csr_file=dict(type="str"),
principal=dict(type="str"),
add_principal=dict(type="bool", required=False, aliases=["add"]),
profile_id=dict(type="str", aliases=["profile"], required=False),
# revoked
revocation_reason=dict(type="raw", aliases=["reason"]),
# general
serial_number=dict(type="int"),
ca=dict(type="str"),
chain=dict(type="bool", required=False),
certificate_out=dict(type="str", required=False),
# state
state=dict(
type="str",
required=True,
choices=[
"requested", "held", "released", "revoked", "retrieved"
]
),
),
mutually_exclusive=[["csr", "csr_file"]],
required_if=[
('state', 'requested', ['principal']),
('state', 'retrieved', ['serial_number']),
('state', 'held', ['serial_number']),
('state', 'released', ['serial_number']),
('state', 'revoked', ['serial_number', 'revocation_reason']),
],
supports_check_mode=False,
)
ansible_module._ansible_debug = True
# Get parameters
# requested
csr = ansible_module.params_get("csr")
csr_file = ansible_module.params_get("csr_file")
principal = ansible_module.params_get("principal")
add_principal = ansible_module.params_get("add_principal")
profile = ansible_module.params_get("profile_id")
# revoked
reason = ansible_module.params_get("revocation_reason")
# general
serial_number = ansible_module.params.get("serial_number")
ca = ansible_module.params_get("ca")
chain = ansible_module.params_get("chain")
certificate_out = ansible_module.params_get("certificate_out")
# state
state = ansible_module.params_get("state")
# Check parameters
if ansible_module.params_get("ipaapi_context") == "server":
ansible_module.fail_json(
msg="Context 'server' for ipacert is not yet supported."
)
invalid = []
if state == "requested":
invalid = ["serial_number", "revocation_reason"]
if csr is None and csr_file is None:
ansible_module.fail_json(
msg="Required 'csr' or 'csr_file' with 'state: requested'.")
else:
invalid = [
"csr", "principal", "add_principal", "profile"
"certificate_out"
]
if state in ["released", "held"]:
invalid.extend(["revocation_reason", "certificate_out", "chain"])
if state == "retrieved":
invalid.append("revocation_reason")
if state == "revoked":
invalid.extend(["certificate_out", "chain"])
elif state == "held":
reason = 6 # certificateHold
ansible_module.params_fail_used_invalid(invalid, state)
# Init
changed = False
exit_args = {}
# Connect to IPA API
# If executed on 'server' contexot, cert plugin uses the IPA RA agent
# TLS client certificate/key, which users are not able to access,
# resulting in a 'permission denied' exception when attempting to connect
# the CA service. Therefore 'client' context in forced for this module.
with ansible_module.ipa_connect(context="client"):
if state == "requested":
if csr_file is not None:
with open(csr_file, "rt") as csr_in:
csr = "".join(csr_in.readlines())
changed, exit_args = do_cert_request(
ansible_module,
csr,
principal,
add_principal,
ca,
profile,
chain,
certificate_out
)
elif state in ("held", "revoked"):
changed, exit_args = do_cert_revoke(
ansible_module, serial_number, reason, ca)
elif state == "released":
changed, exit_args = do_cert_release(
ansible_module, serial_number, ca)
elif state == "retrieved":
changed, exit_args = do_cert_retrieve(
ansible_module, serial_number, ca, chain, certificate_out)
# Done
ansible_module.exit_json(changed=changed, certificate=exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaconfig.py 0000664 0000000 0000000 00000057332 14600563364 0023060 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Chris Procter
# Thomas Woerner
#
# Copyright (C) 2020-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = '''
---
module: ipaconfig
author:
- Chris Procter (@chr15p)
- Thomas Woerner (@t-woerner)
short_description: Modify IPA global config options
description:
- Modify IPA global config options
extends_documentation_fragment:
- ipamodule_base_docs
options:
maxusername:
description: Set the maximum username length between 1-255
required: false
type: int
aliases: ['ipamaxusernamelength']
maxhostname:
description: Set the maximum hostname length between 64-255
required: false
type: int
aliases: ['ipamaxhostnamelength']
homedirectory:
description: Set the default location of home directories
required: false
type: str
aliases: ['ipahomesrootdir']
defaultshell:
description: Set the default shell for new users
required: false
type: str
aliases: ['ipadefaultloginshell', 'loginshell']
defaultgroup:
description: Set the default group for new users
required: false
type: str
aliases: ['ipadefaultprimarygroup']
emaildomain:
description: Set the default e-mail domain
required: false
type: str
aliases: ['ipadefaultemaildomain']
searchtimelimit:
description:
- Set maximum amount of time (seconds) for a search
- values -1 to 2147483647 (-1 or 0 is unlimited)
required: false
type: int
aliases: ['ipasearchtimelimit']
searchrecordslimit:
description:
- Set maximum number of records to search
- values -1 to 2147483647 (-1 or 0 is unlimited)
required: false
type: int
aliases: ['ipasearchrecordslimit']
usersearch:
description:
- Set comma-separated list of fields to search for user search
required: false
type: list
elements: str
aliases: ['ipausersearchfields']
groupsearch:
description:
- Set comma-separated list of fields to search for group search
required: false
type: list
elements: str
aliases: ['ipagroupsearchfields']
enable_migration:
description: Enable migration mode
type: bool
required: false
aliases: ['ipamigrationenabled']
groupobjectclasses:
description: Set default group objectclasses (comma-separated list)
required: false
type: list
elements: str
aliases: ['ipagroupobjectclasses']
userobjectclasses:
description: Set default user objectclasses (comma-separated list)
required: false
type: list
elements: str
aliases: ['ipauserobjectclasses']
pwdexpnotify:
description:
- Set number of days's notice of impending password expiration
- values 0 to 2147483647
required: false
type: int
aliases: ['ipapwdexpadvnotify']
configstring:
description: Set extra hashes to generate in password plug-in
required: false
type: list
elements: str
choices:
- "AllowNThash"
- "KDC:Disable Last Success"
- "KDC:Disable Lockout"
- "KDC:Disable Default Preauth for SPNs"
- ""
aliases: ['ipaconfigstring']
selinuxusermaporder:
description: Set order in increasing priority of SELinux users
required: false
type: list
elements: str
aliases: ['ipaselinuxusermaporder']
selinuxusermapdefault:
description: Set default SELinux user when no match found in map rule
required: false
type: str
aliases: ['ipaselinuxusermapdefault']
pac_type:
description: set default types of PAC supported for services
required: false
type: list
elements: str
choices: ["MS-PAC", "PAD", "nfs:NONE", ""]
aliases: ["ipakrbauthzdata"]
user_auth_type:
description: set default types of supported user authentication
required: false
type: list
elements: str
choices: ["password", "radius", "otp", "pkinit", "hardened", "idp",
"disabled", ""]
aliases: ["ipauserauthtype"]
ca_renewal_master_server:
description: Renewal master for IPA certificate authority.
required: false
type: str
domain_resolution_order:
description: set list of domains used for short name qualification
required: false
type: list
elements: str
aliases: ["ipadomainresolutionorder"]
enable_sid:
description: >
New users and groups automatically get a SID assigned.
Cannot be deactivated once activated. Requires IPA 4.9.8+.
required: false
type: bool
netbios_name:
description: >
NetBIOS name of the IPA domain. Requires IPA 4.9.8+
and SID generation to be activated.
required: false
type: str
add_sids:
description: >
Add SIDs for existing users and groups. Requires IPA 4.9.8+
and SID generation to be activated.
required: false
type: bool
'''
EXAMPLES = '''
---
- name: Playbook to handle global configuration options
hosts: ipaserver
become: true
tasks:
- name: return current values of the global configuration options
ipaconfig:
ipaadmin_password: SomeADMINpassword
register: result
- name: display default login shell
debug:
msg: '{{ result.config.defaultshell[0] }}'
- name: set defaultshell and maxusername
ipaconfig:
ipaadmin_password: SomeADMINpassword
defaultshell: /bin/bash
maxusername: 64
- name: Playbook to enable SID and generate users and groups SIDs
hosts: ipaserver
tasks:
- name: Enable SID and generate users and groups SIDS
ipaconfig:
ipaadmin_password: SomeADMINpassword
enable_sid: yes
add_sids: yes
- name: Playbook to change IPA domain netbios name
hosts: ipaserver
tasks:
- name: Enable SID and generate users and groups SIDS
ipaconfig:
ipaadmin_password: SomeADMINpassword
enable_sid: yes
netbios_name: IPADOM
'''
RETURN = '''
config:
description: Dict of all global config options
returned: When no options are set
type: dict
contains:
maxusername:
description: maximum username length
type: int
returned: always
maxhostname:
description: maximum hostname length
type: int
returned: always
homedirectory:
description: default location of home directories
type: str
returned: always
defaultshell:
description: default shell for new users
type: str
returned: always
defaultgroup:
description: default group for new users
type: str
returned: always
emaildomain:
description: default e-mail domain
type: str
returned: always
searchtimelimit:
description: maximum amount of time (seconds) for a search
type: int
returned: always
searchrecordslimit:
description: maximum number of records to search
type: int
returned: always
usersearch:
description: list of fields to search in user search
type: list
elements: str
returned: always
groupsearch:
description: list of fields to search in group search
type: list
elements: str
returned: always
enable_migration:
description: Enable migration mode
type: bool
returned: always
groupobjectclasses:
description: default group objectclasses (comma-separated list)
type: list
elements: str
returned: always
userobjectclasses:
description: default user objectclasses (comma-separated list)
type: list
elements: str
returned: always
pwdexpnotify:
description: number of days's notice of impending password expiration
type: str
returned: always
configstring:
description: extra hashes to generate in password plug-in
type: list
elements: str
returned: always
selinuxusermaporder:
description: order in increasing priority of SELinux users
type: list
elements: str
returned: always
selinuxusermapdefault:
description: default SELinux user when no match is found in map rule
type: str
returned: always
pac_type:
description: default types of PAC supported for services
type: list
elements: str
returned: always
user_auth_type:
description: default types of supported user authentication
type: str
returned: always
ca_renewal_master_server:
description: master for IPA certificate authority.
type: str
returned: always
domain_resolution_order:
description: list of domains used for short name qualification
type: list
elements: str
returned: always
enable_sid:
description: >
new users and groups automatically get a SID assigned.
Requires IPA 4.9.8+.
type: str
returned: always
netbios_name:
description: NetBIOS name of the IPA domain. Requires IPA 4.9.8+.
type: str
returned: if enable_sid is True
'''
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, ipalib_errors
def config_show(module):
_result = module.ipa_command_no_name("config_show", {"all": True})
return _result["result"]
def get_netbios_name(module):
try:
_result = module.ipa_command_no_name("trustconfig_show", {"all": True})
except Exception: # pylint: disable=broad-except
return None
return _result["result"]["ipantflatname"][0]
def is_enable_sid(module):
"""When 'enable_sid' is true admin user and admins group have SID set."""
_result = module.ipa_command("user_show", "admin", {"all": True})
sid = _result["result"].get("ipantsecurityidentifier", [""])
if not sid[0].endswith("-500"):
return False
_result = module.ipa_command("group_show", "admins", {"all": True})
sid = _result["result"].get("ipantsecurityidentifier", [""])
if not sid[0].endswith("-512"):
return False
return True
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
maxusername=dict(type="int", required=False,
aliases=['ipamaxusernamelength']),
maxhostname=dict(type="int", required=False,
aliases=['ipamaxhostnamelength']),
homedirectory=dict(type="str", required=False,
aliases=['ipahomesrootdir']),
defaultshell=dict(type="str", required=False,
aliases=['ipadefaultloginshell',
'loginshell']),
defaultgroup=dict(type="str", required=False,
aliases=['ipadefaultprimarygroup']),
emaildomain=dict(type="str", required=False,
aliases=['ipadefaultemaildomain']),
searchtimelimit=dict(type="int", required=False,
aliases=['ipasearchtimelimit']),
searchrecordslimit=dict(type="int", required=False,
aliases=['ipasearchrecordslimit']),
usersearch=dict(type="list", elements="str", required=False,
aliases=['ipausersearchfields']),
groupsearch=dict(type="list", elements="str", required=False,
aliases=['ipagroupsearchfields']),
enable_migration=dict(type="bool", required=False,
aliases=['ipamigrationenabled']),
groupobjectclasses=dict(type="list", elements="str",
required=False,
aliases=['ipagroupobjectclasses']),
userobjectclasses=dict(type="list", elements="str", required=False,
aliases=['ipauserobjectclasses']),
pwdexpnotify=dict(type="int", required=False,
aliases=['ipapwdexpadvnotify']),
configstring=dict(type="list", elements="str", required=False,
aliases=['ipaconfigstring'],
choices=["AllowNThash",
"KDC:Disable Last Success",
"KDC:Disable Lockout",
"KDC:Disable Default Preauth for SPNs",
""]), # noqa E128
selinuxusermaporder=dict(type="list", elements="str",
required=False,
aliases=['ipaselinuxusermaporder']),
selinuxusermapdefault=dict(type="str", required=False,
aliases=['ipaselinuxusermapdefault']),
pac_type=dict(type="list", elements="str", required=False,
aliases=["ipakrbauthzdata"],
choices=["MS-PAC", "PAD", "nfs:NONE", ""]),
user_auth_type=dict(type="list", elements="str", required=False,
choices=["password", "radius", "otp",
"pkinit", "hardened", "idp",
"disabled", ""],
aliases=["ipauserauthtype"]),
ca_renewal_master_server=dict(type="str", required=False),
domain_resolution_order=dict(type="list", elements="str",
required=False,
aliases=["ipadomainresolutionorder"]),
enable_sid=dict(type="bool", required=False),
add_sids=dict(type="bool", required=False),
netbios_name=dict(type="str", required=False),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
field_map = {
"maxusername": "ipamaxusernamelength",
"maxhostname": "ipamaxhostnamelength",
"homedirectory": "ipahomesrootdir",
"defaultshell": "ipadefaultloginshell",
"defaultgroup": "ipadefaultprimarygroup",
"emaildomain": "ipadefaultemaildomain",
"searchtimelimit": "ipasearchtimelimit",
"searchrecordslimit": "ipasearchrecordslimit",
"usersearch": "ipausersearchfields",
"groupsearch": "ipagroupsearchfields",
"enable_migration": "ipamigrationenabled",
"groupobjectclasses": "ipagroupobjectclasses",
"userobjectclasses": "ipauserobjectclasses",
"pwdexpnotify": "ipapwdexpadvnotify",
"configstring": "ipaconfigstring",
"selinuxusermaporder": "ipaselinuxusermaporder",
"selinuxusermapdefault": "ipaselinuxusermapdefault",
"pac_type": "ipakrbauthzdata",
"user_auth_type": "ipauserauthtype",
"ca_renewal_master_server": "ca_renewal_master_server",
"domain_resolution_order": "ipadomainresolutionorder",
"enable_sid": "enable_sid",
"netbios_name": "netbios_name",
"add_sids": "add_sids",
}
reverse_field_map = {v: k for k, v in field_map.items()}
allow_empty_list_item = ["pac_type", "user_auth_type", "configstring"]
params = {}
for x in field_map:
val = ansible_module.params_get(
x, allow_empty_list_item=x in allow_empty_list_item)
if val is not None:
params[field_map.get(x, x)] = val
if params.get("ipamigrationenabled") is not None:
params["ipamigrationenabled"] = \
str(params["ipamigrationenabled"]).upper()
if params.get("ipaselinuxusermaporder", None):
params["ipaselinuxusermaporder"] = \
"$".join(params["ipaselinuxusermaporder"])
if params.get("ipadomainresolutionorder", None):
params["ipadomainresolutionorder"] = \
":".join(params["ipadomainresolutionorder"])
if params.get("ipausersearchfields", None):
params["ipausersearchfields"] = \
",".join(params["ipausersearchfields"])
if params.get("ipagroupsearchfields", None):
params["ipagroupsearchfields"] = \
",".join(params["ipagroupsearchfields"])
# verify limits on INT values.
args_with_limits = [
("ipamaxusernamelength", 1, 255),
("ipamaxhostnamelength", 64, 255),
("ipasearchtimelimit", -1, 2147483647),
("ipasearchrecordslimit", -1, 2147483647),
("ipapwdexpadvnotify", 0, 2147483647),
]
for arg, minimum, maximum in args_with_limits:
if arg in params and (params[arg] > maximum or params[arg] < minimum):
ansible_module.fail_json(
msg="Argument '%s' must be between %d and %d."
% (arg, minimum, maximum))
changed = False
exit_args = {}
# Connect to IPA API (enable_sid requires context == 'client')
with ansible_module.ipa_connect(context="client"):
has_enable_sid = ansible_module.ipa_command_param_exists(
"config_mod", "enable_sid")
result = config_show(ansible_module)
if params:
# Verify ipauserauthtype(s)
if "ipauserauthtype" in params and params["ipauserauthtype"]:
_invalid = ansible_module.ipa_command_invalid_param_choices(
"config_mod", "ipauserauthtype", params["ipauserauthtype"])
if _invalid:
ansible_module.fail_json(
msg="The use of userauthtype '%s' is not "
"supported by your IPA version" % "','".join(_invalid))
enable_sid = params.get("enable_sid")
sid_is_enabled = has_enable_sid and is_enable_sid(ansible_module)
if sid_is_enabled and enable_sid is False:
ansible_module.fail_json(msg="SID cannot be disabled.")
netbios_name = params.get("netbios_name")
add_sids = params.get("add_sids")
if has_enable_sid:
if (
netbios_name
and netbios_name == get_netbios_name(ansible_module)
):
del params["netbios_name"]
netbios_name = None
if not add_sids and "add_sids" in params:
del params["add_sids"]
if any([netbios_name, add_sids]):
if sid_is_enabled:
params["enable_sid"] = True
else:
if not enable_sid:
ansible_module.fail_json(
msg="SID generation must be enabled for "
"'netbios_name' and 'add_sids'. Use "
"'enable_sid: yes'."
)
else:
if sid_is_enabled and "enable_sid" in params:
del params["enable_sid"]
else:
if any([enable_sid, netbios_name, add_sids is not None]):
ansible_module.fail_json(
msg="This version of IPA does not support enable_sid, "
"add_sids or netbios_name setting through the "
"config module"
)
params = {
k: v for k, v in params.items()
if k not in result or result[k] != v
}
# Remove empty string args from params if result arg is not set
for k in ["ipakrbauthzdata", "ipauserauthtype", "ipaconfigstring"]:
if k not in result and k in params and params[k] == [""]:
del params[k]
if params \
and not compare_args_ipa(ansible_module, params, result):
changed = True
if not ansible_module.check_mode:
try:
ansible_module.ipa_command_no_name("config_mod",
params)
except ipalib_errors.EmptyModlist:
changed = False
else:
del result['dn']
type_map = {"str": str, "int": int, "list": list, "bool": bool}
for key, value in result.items():
k = reverse_field_map.get(key, key)
if ansible_module.argument_spec.get(k):
arg_type = ansible_module.argument_spec[k]['type']
if k in (
'ipaselinuxusermaporder', 'domain_resolution_order'
):
exit_args[k] = result.get(key)[0].split('$')
elif k in (
'usersearch', 'groupsearch'
):
exit_args[k] = result.get(key)[0].split(',')
elif isinstance(value, str) and arg_type == "list":
exit_args[k] = [value]
elif (
isinstance(value, (tuple, list))
and arg_type in ("str", "int")
):
exit_args[k] = type_map[arg_type](value[0])
elif (
isinstance(value, (tuple, list)) and arg_type == "bool"
):
# FreeIPA 4.9.10+ and 4.10 use proper mapping for
# boolean values, so we need to convert it to str
# for comparison.
# See: https://github.com/freeipa/freeipa/pull/6294
exit_args[k] = str(value[0]).upper() == "TRUE"
else:
if arg_type not in type_map:
raise ValueError(
"Unexpected attribute type: %s" % arg_type)
exit_args[k] = type_map[arg_type](value)
# Add empty pac_type and user_auth_type if they are not set
for key in ["pac_type", "user_auth_type"]:
if key not in exit_args:
exit_args[key] = ""
# Add empty domain_resolution_order if it is not set
if "domain_resolution_order" not in exit_args:
exit_args["domain_resolution_order"] = []
# Set enable_sid
if has_enable_sid:
exit_args["enable_sid"] = is_enable_sid(ansible_module)
exit_args["netbios_name"] = get_netbios_name(ansible_module)
# Done
ansible_module.exit_json(changed=changed, config=exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipadelegation.py 0000664 0000000 0000000 00000022277 14600563364 0023726 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2020-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipadelegation
short_description: Manage FreeIPA delegations
description: Manage FreeIPA delegations and delegation attributes
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of delegation name strings.
type: list
elements: str
required: true
aliases: ["aciname"]
permission:
description: Permissions to grant (read, write). Default is write.
type: list
elements: str
required: false
aliases: ["permissions"]
attribute:
description: Attribute list to which the delegation applies
type: list
elements: str
required: false
aliases: ["attrs"]
membergroup:
description: User group to apply delegation to
type: str
required: false
aliases: ["memberof"]
group:
description: User group ACI grants access to
type: str
required: false
action:
description: Work on delegation or member level.
type: str
choices: ["delegation", "member"]
default: delegation
required: false
state:
description: The state to ensure.
type: str
choices: ["present", "absent"]
default: present
required: false
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure delegation "basic manager attributes" is present
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
- employeetype
group: managers
membergroup: employees
# Ensure delegation "basic manager attributes" member attribute
# departmentnumber is present
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- departmentnumber
action: member
# Ensure delegation "basic manager attributes" member attributes
# employeetype and employeenumber are present
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- employeenumber
- employeetype
action: member
state: absent
# Ensure delegation "basic manager attributes" is absent
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
def find_delegation(module, name):
"""Find if a delegation with the given name already exist."""
try:
_result = module.ipa_command("delegation_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if delegation name is not found.
return None
return _result["result"]
def gen_args(permission, attribute, membergroup, group):
_args = {}
if permission is not None:
_args["permissions"] = permission
if attribute is not None:
_args["attrs"] = attribute
if membergroup is not None:
_args["memberof"] = membergroup
if group is not None:
_args["group"] = group
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["aciname"],
required=True),
# present
permission=dict(required=False, type='list', elements="str",
aliases=["permissions"], default=None),
attribute=dict(required=False, type='list', elements="str",
aliases=["attrs"], default=None),
membergroup=dict(type="str", aliases=["memberof"], default=None),
group=dict(type="str", default=None),
action=dict(type="str", default="delegation",
choices=["member", "delegation"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
permission = ansible_module.params_get_lowercase("permission")
attribute = ansible_module.params_get_lowercase("attribute")
membergroup = ansible_module.params_get("membergroup")
group = ansible_module.params_get_lowercase("group")
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one delegation be added at a time.")
if action == "member":
invalid = ["permission", "membergroup", "group"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["permission", "membergroup", "group"]
if action == "delegation":
invalid.append("attribute")
ansible_module.params_fail_used_invalid(invalid, state, action)
if permission is not None:
perm = [p for p in permission if p not in ("read", "write")]
if perm:
ansible_module.fail_json(msg="Invalid permission '%s'" % perm)
if len(set(permission)) != len(permission):
ansible_module.fail_json(
msg="Invalid permission '%s', items are not unique" %
repr(permission))
if attribute is not None:
if len(set(attribute)) != len(attribute):
ansible_module.fail_json(
msg="Invalid attribute '%s', items are not unique" %
repr(attribute))
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
args = {}
# Make sure delegation exists
res_find = find_delegation(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(permission, attribute, membergroup, group)
if action == "delegation":
# Found the delegation
if res_find is None:
commands.append([name, "delegation_add", args])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No delegation '%s'" % name)
if attribute is None:
ansible_module.fail_json(msg="No attributes given")
# New attribute list (add given ones to find result)
# Make list with unique entries
attrs = list(set(list(res_find["attrs"]) + attribute))
args["attrs"] = attrs
elif state == "absent":
if action == "delegation":
if res_find is not None:
commands.append([name, "delegation_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No delegation '%s'" % name)
if attribute is None:
ansible_module.fail_json(msg="No attributes given")
# New attribute list (remove given ones from find result)
# Make list with unique entries
attrs = list(set(res_find["attrs"]) - set(attribute))
if len(attrs) < 1:
ansible_module.fail_json(
msg="At minimum one attribute is needed.")
args["attrs"] = attrs
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Manage members
if (
args and res_find and
not compare_args_ipa(ansible_module, args, res_find)
):
commands.append([name, "delegation_mod", args])
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipadnsconfig.py 0000664 0000000 0000000 00000020521 14600563364 0023553 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipadnsconfig
short_description: Manage FreeIPA dnsconfig
description: Manage FreeIPA dnsconfig
extends_documentation_fragment:
- ipamodule_base_docs
options:
forwarders:
description: The list of global DNS forwarders.
required: false
type: list
elements: dict
suboptions:
ip_address:
description: The forwarder nameserver IP address list (IPv4 and IPv6).
type: str
required: true
port:
description: The port to forward requests to.
type: int
required: false
forward_policy:
description:
Global forwarding policy. Set to "none" to disable any configured
global forwarders.
type: str
required: false
choices: ['only', 'first', 'none']
aliases: ["forwardpolicy"]
allow_sync_ptr:
description:
Allow synchronization of forward (A, AAAA) and reverse (PTR) records.
required: false
type: bool
action:
description: |
Work on dnsconfig or member level. It can be one of `member` or
`dnsconfig`. Only `forwarders` can be managed with `action: member`.
type: str
default: "dnsconfig"
choices: ["member", "dnsconfig"]
state:
description: |
The state to ensure. It can be one of `present` or `absent`.
`absent` can only be used with `action: member` and `forwarders`.
type: str
default: present
choices: ["present", "absent"]
author:
- Rafael Guterres Jeffman (@rjeffman)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure global DNS forward configuration, allowing PTR record synchronization.
- ipadnsconfig:
ipaadmin_password: SomeADMINpassword
forwarders:
- ip_address: 8.8.4.4
- ip_address: 2001:4860:4860::8888
port: 53
forward_policy: only
allow_sync_ptr: yes
# Ensure forwarder is absent.
- ipadnsconfig:
ipaadmin_password: SomeADMINpassword
forwarders:
- ip_address: 2001:4860:4860::8888
port: 53
state: absent
action: member
# Disable PTR record synchronization.
- ipadnsconfig:
ipaadmin_password: SomeADMINpassword
allow_sync_ptr: no
# Disable global forwarders.
- ipadnsconfig:
ipaadmin_password: SomeADMINpassword
forward_policy: none
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, is_ipv4_addr, is_ipv6_addr
def find_dnsconfig(module):
_args = {
"all": True,
}
_result = module.ipa_command_no_name("dnsconfig_show", _args)
if "result" in _result:
if _result["result"].get('idnsforwarders', None) is None:
_result["result"]['idnsforwarders'] = ['']
return _result["result"]
module.fail_json(msg="Could not retrieve current DNS configuration.")
return None
def gen_args(module, state, action, dnsconfig, forwarders, forward_policy,
allow_sync_ptr):
_args = {}
if forwarders:
_forwarders = []
for forwarder in forwarders:
ip_address = forwarder.get('ip_address')
port = forwarder.get('port')
if not (is_ipv4_addr(ip_address) or is_ipv6_addr(ip_address)):
module.fail_json(
msg="Invalid IP for DNS forwarder: %s" % ip_address)
if port is None:
_forwarders.append(ip_address)
else:
_forwarders.append('%s port %d' % (ip_address, port))
global_forwarders = dnsconfig.get('idnsforwarders', [])
if state == 'absent':
if action == "member":
_args['idnsforwarders'] = [
fwd for fwd in global_forwarders if fwd not in _forwarders]
# When all forwarders should be excluded,
# use an empty string ('').
if not _args['idnsforwarders']:
_args['idnsforwarders'] = ['']
elif state == 'present':
if action == "member":
_args['idnsforwarders'] = \
list(set(list(_forwarders) + list(global_forwarders)))
else:
_args['idnsforwarders'] = _forwarders
# If no forwarders should be added, remove argument.
if not _args['idnsforwarders']:
del _args['idnsforwarders']
else:
# shouldn't happen, but let's be paranoid.
module.fail_json(msg="Invalid state: %s" % state)
if forward_policy is not None:
_args['idnsforwardpolicy'] = forward_policy
if allow_sync_ptr is not None:
if module.ipa_check_version("<", "4.9.10"):
_args['idnsallowsyncptr'] = "TRUE" if allow_sync_ptr else "FALSE"
else:
_args['idnsallowsyncptr'] = allow_sync_ptr
return _args
def main():
forwarder_spec = dict(
ip_address=dict(type="str", required=True),
port=dict(type="int", required=False, default=None)
)
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# dnsconfig
forwarders=dict(type='list', elements="dict", default=None,
required=False,
options=dict(**forwarder_spec)),
forward_policy=dict(type='str', required=False, default=None,
choices=['only', 'first', 'none'],
aliases=["forwardpolicy"]),
allow_sync_ptr=dict(type='bool', required=False, default=None),
# general
action=dict(type="str", default="dnsconfig",
choices=["member", "dnsconfig"]),
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# dnsconfig
forwarders = ansible_module.params_get('forwarders') or []
forward_policy = ansible_module.params_get('forward_policy')
allow_sync_ptr = ansible_module.params_get('allow_sync_ptr')
action = ansible_module.params_get('action')
state = ansible_module.params_get('state')
# Check parameters.
invalid = []
if state == "present" and action == "member":
invalid = ['forward_policy', 'allow_sync_ptr']
if state == 'absent':
if action != "member":
ansible_module.fail_json(
msg="State 'absent' is only valid with action 'member'.")
invalid = ['forward_policy', 'allow_sync_ptr']
ansible_module.params_fail_used_invalid(invalid, state)
# Init
changed = False
# Connect to IPA API
with ansible_module.ipa_connect():
res_find = find_dnsconfig(ansible_module)
args = gen_args(ansible_module, state, action, res_find, forwarders,
forward_policy, allow_sync_ptr)
# Execute command only if configuration changes.
if not compare_args_ipa(ansible_module, args, res_find):
try:
if not ansible_module.check_mode:
ansible_module.ipa_command_no_name('dnsconfig_mod', args)
# If command did not fail, something changed.
changed = True
except Exception as e:
msg = str(e)
ansible_module.fail_json(msg="dnsconfig_mod: %s" % msg)
# Done
ansible_module.exit_json(changed=changed)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipadnsforwardzone.py 0000664 0000000 0000000 00000033430 14600563364 0024651 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Chris Procter
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = '''
---
module: ipadnsforwardzone
author:
- Chris Procter (@chr15p)
- Thomas Woerner (@t-woerner)
short_description: Manage FreeIPA DNS Forwarder Zones
description:
- Add and delete an IPA DNS Forwarder Zones using IPA API
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description:
- The DNS zone name which needs to be managed.
type: list
elements: str
required: true
aliases: ["cn"]
action:
description: |
Work on dnsforwardzone or member level. It can be one of `member` or
`dnsforwardzone`.
type: str
default: "dnsforwardzone"
choices: ["member", "dnsforwardzone"]
state:
description: State to ensure
type: str
required: false
default: present
choices: ["present", "absent", "enabled", "disabled"]
forwarders:
description:
- List of the DNS servers to forward to
type: list
elements: dict
aliases: ["idnsforwarders"]
suboptions:
ip_address:
description: Forwarder IP address (either IPv4 or IPv6).
required: true
type: str
port:
description: Forwarder port.
required: false
type: int
forwardpolicy:
description: Per-zone conditional forwarding policy
type: str
required: false
choices: ["only", "first", "none"]
aliases: ["idnsforwardpolicy", "forward_policy"]
skip_overlap_check:
description:
- Force DNS zone creation even if it will overlap with an existing zone.
type: bool
required: false
permission:
description:
- Allow DNS Forward Zone to be managed.
required: false
type: bool
aliases: ["managedby"]
'''
EXAMPLES = '''
# Ensure dns zone is present
- ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
state: present
name: example.com
forwarders:
- ip_address: 8.8.8.8
- ip_address: 4.4.4.4
forwardpolicy: first
skip_overlap_check: true
# Ensure dns zone is present, with forwarder on non-default port
- ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
state: present
name: example.com
forwarders:
- ip_address: 8.8.8.8
port: 8053
forwardpolicy: first
skip_overlap_check: true
# Ensure that dns zone is removed
- ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
name: example.com
state: absent
'''
RETURN = '''
'''
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
def find_dnsforwardzone(module, name):
_args = {
"all": True,
"idnsname": name
}
_result = module.ipa_command("dnsforwardzone_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one dnsforwardzone '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
return None
def gen_args(forwarders, forwardpolicy, skip_overlap_check):
_args = {}
if forwarders is not None:
_args["idnsforwarders"] = forwarders
if forwardpolicy is not None:
_args["idnsforwardpolicy"] = forwardpolicy
if skip_overlap_check is not None:
_args["skip_overlap_check"] = skip_overlap_check
return _args
def forwarder_list(forwarders):
"""Convert the forwarder dict into a list compatible with IPA API."""
if forwarders is None:
return None
fwd_list = []
for forwarder in forwarders:
if forwarder.get('port', None) is not None:
formatter = "{ip_address} port {port}"
else:
formatter = "{ip_address}"
fwd_list.append(to_text(formatter.format(**forwarder)))
return fwd_list
def fix_resource_data_types(resource):
"""Fix resource data types."""
# When running in client context, some data might
# not come as a list, so we need to fix it before
# applying any modifications to it.
forwarders = resource["idnsforwarders"]
if isinstance(forwarders, str):
forwarders = [forwarders]
elif isinstance(forwarders, tuple):
forwarders = list(forwarders)
resource["idnsforwarders"] = forwarders
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
forwarders=dict(type="list", default=None, required=False,
aliases=["idnsforwarders"], elements='dict',
options=dict(
ip_address=dict(type='str', required=True),
port=dict(type='int', required=False,
default=None),
)),
forwardpolicy=dict(type='str',
aliases=["idnsforwardpolicy", "forward_policy"],
required=False,
choices=['only', 'first', 'none']),
skip_overlap_check=dict(type='bool', required=False),
permission=dict(type='bool', required=False,
aliases=['managedby']),
action=dict(type="str", default="dnsforwardzone",
choices=["member", "dnsforwardzone"]),
# state
state=dict(type='str', default='present',
choices=['present', 'absent', 'enabled', 'disabled']),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
names = ansible_module.params_get("name")
action = ansible_module.params_get("action")
forwarders = forwarder_list(
ansible_module.params_get("forwarders"))
forwardpolicy = ansible_module.params_get("forwardpolicy")
skip_overlap_check = ansible_module.params_get("skip_overlap_check")
permission = ansible_module.params_get("permission")
state = ansible_module.params_get("state")
if state == 'present' and len(names) != 1:
ansible_module.fail_json(
msg="Only one dnsforwardzone can be added at a time.")
if state == 'absent' and len(names) < 1:
ansible_module.fail_json(msg="No name given.")
# absent stae means delete if the action is NOT member but update if it is
# if action is member then update an exisiting resource
# and if action is not member then create a resource
if state == "absent" and action == "dnsforwardzone":
operation = "del"
elif action == "member":
operation = "update"
else:
operation = "add"
invalid = []
if state in ["enabled", "disabled"]:
if action == "member":
ansible_module.fail_json(
msg="Action `member` cannot be used with state `%s`"
% (state))
invalid = [
"forwarders", "forwardpolicy", "skip_overlap_check", "permission"
]
wants_enable = state == "enabled"
if operation == "del":
invalid = [
"forwarders", "forwardpolicy", "skip_overlap_check", "permission"
]
ansible_module.params_fail_used_invalid(invalid, state, action)
changed = False
exit_args = {}
args = {}
is_enabled = "IGNORE"
# Connect to IPA API
with ansible_module.ipa_connect():
# we need to determine 3 variables
# args = the values we want to change/set
# command = the ipa api command to call del, add, or mod
# is_enabled = is the current resource enabled (True)
# disabled (False) and do we care (IGNORE)
for name in names:
commands = []
command = None
# Make sure forwardzone exists
existing_resource = find_dnsforwardzone(ansible_module, name)
# validate parameters
if state == 'present':
if existing_resource is None and not forwarders:
ansible_module.fail_json(msg='No forwarders specified.')
if existing_resource is None:
if operation == "add":
# does not exist but should be present
# determine args
args = gen_args(forwarders, forwardpolicy,
skip_overlap_check)
# set command
command = "dnsforwardzone_add"
# enabled or disabled?
elif operation == "update":
# does not exist and is updating
# trying to update something that doesn't exist, so error
ansible_module.fail_json(
msg="dnsforwardzone '%s' not found." % (name))
elif operation == "del":
# there's nothnig to do.
continue
else: # existing_resource is not None
fix_resource_data_types(existing_resource)
if state != "absent":
if forwarders:
forwarders = list(
set(existing_resource["idnsforwarders"]
+ forwarders))
else:
if forwarders:
forwarders = list(
set(existing_resource["idnsforwarders"])
- set(forwarders))
if operation == "add":
# exists and should be present, has it changed?
# determine args
args = gen_args(
forwarders, forwardpolicy, skip_overlap_check)
if 'skip_overlap_check' in args:
del args['skip_overlap_check']
# set command
if not compare_args_ipa(
ansible_module, args, existing_resource):
command = "dnsforwardzone_mod"
elif operation == "del":
# exists but should be absent
# set command
command = "dnsforwardzone_del"
args = {}
elif operation == "update":
# exists and is updating
# calculate the new forwarders and mod
args = gen_args(
forwarders, forwardpolicy, skip_overlap_check)
if "skip_overlap_check" in args:
del args['skip_overlap_check']
# command
if not compare_args_ipa(
ansible_module, args, existing_resource):
command = "dnsforwardzone_mod"
if state in ['enabled', 'disabled']:
if existing_resource is not None:
# FreeIPA 4.9.10+ and 4.10 use proper mapping for
# boolean values, so we need to convert it to str
# for comparison.
# See: https://github.com/freeipa/freeipa/pull/6294
is_enabled = (
str(existing_resource["idnszoneactive"][0]).upper()
)
else:
ansible_module.fail_json(
msg="dnsforwardzone '%s' not found." % (name))
# does the enabled state match what we want (if we care)
if is_enabled != "IGNORE":
if wants_enable and is_enabled != "TRUE":
commands.append([name, "dnsforwardzone_enable", {}])
elif not wants_enable and is_enabled != "FALSE":
commands.append([name, "dnsforwardzone_disable", {}])
# if command is set...
if command is not None:
commands.append([name, command, args])
if permission is not None:
if existing_resource is None:
managedby = None
else:
managedby = existing_resource.get('managedby', None)
if permission and managedby is None:
commands.append(
[name, 'dnsforwardzone_add_permission', {}]
)
elif not permission and managedby is not None:
commands.append(
[name, 'dnsforwardzone_remove_permission', {}]
)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0,
**exit_args)
# Execute commands
for _name, command, args in commands:
ansible_module.ipa_command(command, _name, args)
changed = True
# Done
ansible_module.exit_json(changed=changed, dnsforwardzone=exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipadnsrecord.py 0000664 0000000 0000000 00000143056 14600563364 0023575 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
# Thomas Woerner
#
# Copyright (C) 2020-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
"""DNS Record ansible-freeipa module."""
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipadnsrecord
short_description: Manage FreeIPA DNS records
description: Manage FreeIPA DNS records
extends_documentation_fragment:
- ipamodule_base_docs
options:
records:
description: The list of user dns records dicts
required: false
type: list
elements: dict
suboptions:
name:
description: The DNS record name to manage.
type: str
aliases: ["record_name"]
required: true
zone_name:
description: |
The DNS zone name to which DNS record needs to be managed.
Required if not provided globally.
type: str
aliases: ["dnszone"]
required: false
record_type:
description: The type of DNS record.
type: str
choices: ["A", "AAAA", "A6", "AFSDB", "CERT", "CNAME", "DLV", "DNAME",
"DS", "KX", "LOC", "MX", "NAPTR", "NS", "PTR", "SRV",
"SSHFP", "TLSA", "TXT", "URI"]
default: "A"
record_value:
description: Manage DNS record name with these values.
required: false
type: list
elements: str
record_ttl:
description: Set the TTL for the record.
required: false
type: int
del_all:
description: Delete all associated records.
required: false
type: bool
a_rec:
description: Raw A record.
type: list
elements: str
required: false
aliases: ["a_record"]
aaaa_rec:
description: Raw AAAA record.
type: list
elements: str
required: false
aliases: ["aaaa_record"]
a6_rec:
description: Raw A6 record.
type: list
elements: str
required: false
aliases: ["a6_record"]
afsdb_rec:
description: Raw AFSDB record.
type: list
elements: str
required: false
aliases: ["afsdb_record"]
cert_rec:
description: Raw CERT record.
type: list
elements: str
required: false
aliases: ["cert_record"]
cname_rec:
description: Raw CNAME record.
type: list
elements: str
required: false
aliases: ["cname_record"]
dlv_rec:
description: Raw DLV record.
type: list
elements: str
required: false
aliases: ["dlv_record"]
dname_rec:
description: Raw DNAM record.
type: list
elements: str
required: false
aliases: ["dname_record"]
ds_rec:
description: Raw DS record.
type: list
elements: str
required: false
aliases: ["ds_record"]
kx_rec:
description: Raw KX record.
type: list
elements: str
required: false
aliases: ["kx_record"]
loc_rec:
description: Raw LOC record.
type: list
elements: str
required: false
aliases: ["loc_record"]
mx_rec:
description: Raw MX record.
type: list
elements: str
required: false
aliases: ["mx_record"]
naptr_rec:
description: Raw NAPTR record.
type: list
elements: str
required: false
aliases: ["naptr_record"]
ns_rec:
description: Raw NS record.
type: list
elements: str
required: false
aliases: ["ns_record"]
ptr_rec:
description: Raw PTR record.
type: list
elements: str
required: false
aliases: ["ptr_record"]
srv_rec:
description: Raw SRV record.
type: list
elements: str
required: false
aliases: ["srv_record"]
sshfp_rec:
description: Raw SSHFP record.
type: list
elements: str
required: false
aliases: ["sshfp_record"]
tlsa_rec:
description: Raw TLSA record.
type: list
elements: str
required: false
aliases: ["tlsa_record"]
txt_rec:
description: Raw TXT record.
type: list
elements: str
required: false
aliases: ["txt_record"]
uri_rec:
description: Raw URI record.
type: list
elements: str
required: false
aliases: ["uri_record"]
ip_address:
description: IP adresses for A or AAAA records.
required: false
type: str
a_ip_address:
description: IP adresses for A records.
required: false
type: str
a_create_reverse:
description: |
Create reverse record for A records.
There is no equivalent to remove reverse records.
type: bool
required: false
aaaa_ip_address:
description: IP adresses for AAAA records.
required: false
type: str
aaaa_create_reverse:
description: |
Create reverse record for AAAA records.
There is no equivalent to remove reverse records.
type: bool
required: false
create_reverse:
description: |
Create reverse record for A or AAAA record types.
There is no equivalent to remove reverse records.
type: bool
required: false
aliases: ["reverse"]
a6_data:
description: A6 record data.
required: false
type: str
afsdb_subtype:
description: AFSDB Subtype
required: false
type: int
afsdb_hostname:
description: AFSDB Hostname
required: false
type: str
cert_type:
description: CERT Certificate Type
required: false
type: int
cert_key_tag:
description: CERT Key Tag
required: false
type: int
cert_algorithm:
description: CERT Algorithm
required: false
type: int
cert_certificate_or_crl:
description: CERT Certificate or Certificate Revocation List (CRL).
required: false
type: str
cname_hostname:
description: A hostname which this alias hostname points to.
required: false
type: str
dlv_key_tag:
description: DLV Key Tag
required: false
type: int
dlv_algorithm:
description: DLV Algorithm
required: false
type: int
dlv_digest_type:
description: DLV Digest Type
required: false
type: int
dlv_digest:
description: DLV Digest
required: false
type: str
dname_target:
description: DNAME Target
required: false
type: str
ds_key_tag:
description: DS Key Tag
required: false
type: int
ds_algorithm:
description: DS Algorithm
required: false
type: int
ds_digest_type:
description: DS Digest Type
required: false
type: int
ds_digest:
description: DS Digest
required: false
type: str
kx_preference:
description: |
Preference given to this exchanger. Lower values are more preferred.
required: false
type: int
kx_exchanger:
description: A host willing to act as a key exchanger.
required: false
type: str
loc_lat_deg:
description: LOC Degrees Latitude
required: false
type: int
loc_lat_min:
description: LOC Minutes Latitude
required: false
type: int
loc_lat_sec:
description: LOC Seconds Latitude
required: false
type: float
loc_lat_dir:
description: LOC Direction Latitude
required: false
choices: ["N", "S"]
type: str
loc_lon_deg:
description: LOC Degrees Longitude
required: false
type: int
loc_lon_min:
description: LOC Minutes Longitude
required: false
type: int
loc_lon_sec:
description: LOC Seconds Longitude
required: false
type: float
loc_lon_dir:
description: LOC Direction Longitude
required: false
choices: ["E", "W"]
type: str
loc_altitude:
description: LOC Altitude
required: false
type: float
loc_size:
description: LOC Size
required: false
type: float
loc_h_precision:
description: LOC Horizontal Precision
required: false
type: float
loc_v_precision:
description: LOC Vertical Precision
required: false
type: float
mx_preference:
description: |
Preference given to this exchanger. Lower values are more preferred.
required: false
type: int
mx_exchanger:
description: A host willing to act as a mail exchanger.
required: false
type: str
naptr_order:
description: NAPTR Order
required: false
type: int
naptr_preference:
description: NAPTR Preference
required: false
type: int
naptr_flags:
description: NAPTR Flags
required: false
type: str
naptr_service:
description: NAPTR Service
required: false
type: str
naptr_regexp:
description: NAPTR Regular Expression
required: false
type: str
naptr_replacement:
description: NAPTR Replacement
required: false
type: str
ns_hostname:
description: NS Hostname
required: false
type: str
ptr_hostname:
description: The hostname this reverse record points to.
required: false
type: str
srv_priority:
description: |
Lower number means higher priority. Clients will attempt to contact
the server with the lowest-numbered priority they can reach.
required: false
type: int
srv_weight:
description: Relative weight for entries with the same priority.
required: false
type: int
srv_port:
description: SRV Port
required: false
type: int
srv_target:
description: |
The domain name of the target host or '.' if the service is decidedly
not available at this domain.
required: false
type: str
sshfp_algorithm:
description: SSHFP Algorithm
required: False
type: int
sshfp_fp_type:
description: SSHFP Fingerprint Type
required: False
type: int
sshfp_fingerprint:
description: SSHFP Fingerprint
required: False
type: str
txt_data:
description: TXT Text Data
required: false
type: str
tlsa_cert_usage:
description: TLSA Certificate Usage
required: false
type: int
tlsa_selector:
description: TLSA Selector
required: false
type: int
tlsa_matching_type:
description: TLSA Matching Type
required: false
type: int
tlsa_cert_association_data:
description: TLSA Certificate Association Data
required: false
type: str
uri_target:
description: Target Uniform Resource Identifier according to RFC 3986.
required: false
type: str
uri_priority:
description: |
Lower number means higher priority. Clients will attempt to contact
the URI with the lowest-numbered priority they can reach.
required: false
type: int
uri_weight:
description: Relative weight for entries with the same priority.
required: false
type: int
name:
description: The DNS record name to manage.
type: list
elements: str
aliases: ["record_name"]
required: false
zone_name:
description: |
The DNS zone name to which DNS record needs to be managed.
Required if not provided globally.
type: str
aliases: ["dnszone"]
required: false
record_type:
description: The type of DNS record.
type: str
choices: ["A", "AAAA", "A6", "AFSDB", "CERT", "CNAME", "DLV", "DNAME",
"DS", "KX", "LOC", "MX", "NAPTR", "NS", "PTR", "SRV",
"SSHFP", "TLSA", "TXT", "URI"]
default: "A"
record_value:
description: Manage DNS record name with these values.
required: false
type: list
elements: str
record_ttl:
description: Set the TTL for the record.
required: false
type: int
del_all:
description: Delete all associated records.
required: false
type: bool
a_rec:
description: Raw A record.
type: list
elements: str
required: false
aliases: ["a_record"]
aaaa_rec:
description: Raw AAAA record.
type: list
elements: str
required: false
aliases: ["aaaa_record"]
a6_rec:
description: Raw A6 record.
type: list
elements: str
required: false
aliases: ["a6_record"]
afsdb_rec:
description: Raw AFSDB record.
type: list
elements: str
required: false
aliases: ["afsdb_record"]
cert_rec:
description: Raw CERT record.
type: list
elements: str
required: false
aliases: ["cert_record"]
cname_rec:
description: Raw CNAME record.
type: list
elements: str
required: false
aliases: ["cname_record"]
dlv_rec:
description: Raw DLV record.
type: list
elements: str
required: false
aliases: ["dlv_record"]
dname_rec:
description: Raw DNAM record.
type: list
elements: str
required: false
aliases: ["dname_record"]
ds_rec:
description: Raw DS record.
type: list
elements: str
required: false
aliases: ["ds_record"]
kx_rec:
description: Raw KX record.
type: list
elements: str
required: false
aliases: ["kx_record"]
loc_rec:
description: Raw LOC record.
type: list
elements: str
required: false
aliases: ["loc_record"]
mx_rec:
description: Raw MX record.
type: list
elements: str
required: false
aliases: ["mx_record"]
naptr_rec:
description: Raw NAPTR record.
type: list
elements: str
required: false
aliases: ["naptr_record"]
ns_rec:
description: Raw NS record.
type: list
elements: str
required: false
aliases: ["ns_record"]
ptr_rec:
description: Raw PTR record.
type: list
elements: str
required: false
aliases: ["ptr_record"]
srv_rec:
description: Raw SRV record.
type: list
elements: str
required: false
aliases: ["srv_record"]
sshfp_rec:
description: Raw SSHFP record.
type: list
elements: str
required: false
aliases: ["sshfp_record"]
tlsa_rec:
description: Raw TLSA record.
type: list
elements: str
required: false
aliases: ["tlsa_record"]
txt_rec:
description: Raw TXT record.
type: list
elements: str
required: false
aliases: ["txt_record"]
uri_rec:
description: Raw URI record.
type: list
elements: str
required: false
aliases: ["uri_record"]
ip_address:
description: IP adresses for A or AAAA records.
required: false
type: str
a_ip_address:
description: IP adresses for A records.
required: false
type: str
a_create_reverse:
description: |
Create reverse record for A records.
There is no equivalent to remove reverse records.
type: bool
required: false
aaaa_ip_address:
description: IP adresses for AAAA records.
required: false
type: str
aaaa_create_reverse:
description: |
Create reverse record for AAAA records.
There is no equivalent to remove reverse records.
type: bool
required: false
create_reverse:
description: |
Create reverse record for A or AAAA record types.
There is no equivalent to remove reverse records.
type: bool
required: false
aliases: ["reverse"]
a6_data:
description: A6 record data.
required: false
type: str
afsdb_subtype:
description: AFSDB Subtype
required: false
type: int
afsdb_hostname:
description: AFSDB Hostname
required: false
type: str
cert_type:
description: CERT Certificate Type
required: false
type: int
cert_key_tag:
description: CERT Key Tag
required: false
type: int
cert_algorithm:
description: CERT Algorithm
required: false
type: int
cert_certificate_or_crl:
description: CERT Certificate or Certificate Revocation List (CRL).
required: false
type: str
cname_hostname:
description: A hostname which this alias hostname points to.
required: false
type: str
dlv_key_tag:
description: DS Key Tag
required: false
type: int
dlv_algorithm:
description: DLV Algorithm
required: false
type: int
dlv_digest_type:
description: DLV Digest Type
required: false
type: int
dlv_digest:
description: DLV Digest
required: false
type: str
dname_target:
description: DNAME Target
required: false
type: str
ds_key_tag:
description: DS Key Tag
required: false
type: int
ds_algorithm:
description: DS Algorithm
required: false
type: int
ds_digest_type:
description: DS Digest Type
required: false
type: int
ds_digest:
description: DS Digest
required: false
type: str
kx_preference:
description: |
Preference given to this exchanger. Lower values are more preferred.
required: false
type: int
kx_exchanger:
description: A host willing to act as a key exchanger.
required: false
type: str
loc_lat_deg:
description: LOC Degrees Latitude
required: false
type: int
loc_lat_min:
description: LOC Minutes Latitude
required: false
type: int
loc_lat_sec:
description: LOC Seconds Latitude
required: false
type: float
loc_lat_dir:
description: LOC Direction Latitude
required: false
choices: ["N", "S"]
type: str
loc_lon_deg:
description: LOC Degrees Longitude
required: false
type: int
loc_lon_min:
description: LOC Minutes Longitude
required: false
type: int
loc_lon_sec:
description: LOC Seconds Longitude
required: false
type: float
loc_lon_dir:
description: LOC Direction Longitude
required: false
choices: ["E", "W"]
type: str
loc_altitude:
description: LOC Altitude
required: false
type: float
loc_size:
description: LOC Size
required: false
type: float
loc_h_precision:
description: LOC Horizontal Precision
required: false
type: float
loc_v_precision:
description: LOC Vertical Precision
required: false
type: float
mx_preference:
description: |
Preference given to this exchanger. Lower values are more preferred.
required: false
type: int
mx_exchanger:
description: A host willing to act as a mail exchanger.
required: false
type: str
naptr_order:
description: NAPTR Order
required: false
type: int
naptr_preference:
description: NAPTR Preference
required: false
type: int
naptr_flags:
description: NAPTR Flags
required: false
type: str
naptr_service:
description: NAPTR Service
required: false
type: str
naptr_regexp:
description: NAPTR Regular Expression
required: false
type: str
naptr_replacement:
description: NAPTR Replacement
required: false
type: str
ns_hostname:
description: NS Hostname
required: false
type: str
ptr_hostname:
description: The hostname this reverse record points to.
required: false
type: str
srv_priority:
description: |
Lower number means higher priority. Clients will attempt to contact
the server with the lowest-numbered priority they can reach.
required: false
type: int
srv_weight:
description: Relative weight for entries with the same priority.
required: false
type: int
srv_port:
description: SRV Port
required: false
type: int
srv_target:
description: |
The domain name of the target host or '.' if the service is decidedly
not available at this domain.
required: false
type: str
sshfp_algorithm:
description: SSHFP Algorithm
required: False
type: int
sshfp_fp_type:
description: SSHFP Fingerprint Type
required: False
type: int
sshfp_fingerprint:
description: SSHFP Fingerprint
required: False
type: str
txt_data:
description: TXT Text Data
required: false
type: str
tlsa_cert_usage:
description: TLSA Certificate Usage
required: false
type: int
tlsa_selector:
description: TLSA Selector
required: false
type: int
tlsa_matching_type:
description: TLSA Matching Type
required: false
type: int
tlsa_cert_association_data:
description: TLSA Certificate Association Data
required: false
type: str
uri_target:
description: Target Uniform Resource Identifier according to RFC 3986.
required: false
type: str
uri_priority:
description: |
Lower number means higher priority. Clients will attempt to contact
the URI with the lowest-numbered priority they can reach.
required: false
type: int
uri_weight:
description: Relative weight for entries with the same priority.
required: false
type: int
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent", "disabled"]
author:
- Rafael Guterres Jeffman (@rjeffman)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure dns record is present
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: vm-001
zone_name: example.com
record_type: 'AAAA'
record_value: '::1'
# Ensure that dns record exists with a TTL
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: example.com
record_type: 'AAAA'
record_value: '::1'
record_ttl: 300
# Ensure that dns record exists with a reverse record
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host02
zone_name: example.com
record_type: 'AAAA'
record_value: 'fd00::0002'
create_reverse: yes
# Ensure a PTR record is present
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: 5
zone_name: 2.168.192.in-addr.arpa
record_type: 'PTR'
record_value: 'internal.ipa.example.com'
# Ensure a TXT record is present
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: _kerberos
zone_name: example.com
record_type: 'TXT'
record_value: 'EXAMPLE.COM'
# Ensure a SRV record is present
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: _kerberos._udp.example.com
zone_name: example.com
record_type: 'SRV'
record_value: '10 50 88 ipa.example.com'
# Ensure an MX record is present
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: '@'
zone_name: example.com
record_type: 'MX'
record_value: '1 mailserver.example.com'
# Ensure that dns record is absent
- ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: example.com
record_type: 'AAAA'
record_value: '::1'
state: absent
"""
RETURN = """
"""
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, is_ipv4_addr, is_ipv6_addr, ipalib_errors
try:
import dns.reversename
import dns.resolver
except ImportError as _err:
MODULE_IMPORT_ERROR = str(_err)
else:
MODULE_IMPORT_ERROR = None
from ansible.module_utils import six
if six.PY3:
unicode = str
_SUPPORTED_RECORD_TYPES = [
"A", "AAAA", "A6", "AFSDB", "CERT", "CNAME", "DLV", "DNAME", "DS", "KX",
"LOC", "MX", "NAPTR", "NS", "PTR", "SRV", "SSHFP", "TLSA", "TXT", "URI"]
_RECORD_FIELDS = [
"a_rec", "aaaa_rec", "a6_rec", "afsdb_rec", "cert_rec",
"cname_rec", "dlv_rec", "dname_rec", "ds_rec", "kx_rec", "loc_rec",
"mx_rec", "naptr_rec", "ns_rec", "ptr_rec", "srv_rec", "sshfp_rec",
"tlsa_rec", "txt_rec", "uri_rec"
]
# The _PART_MAP structure maps ansible-freeipa attributes to their
# FreeIPA API counterparts. The keys are also used to obtain a list
# of all supported DNS record attributes.
_PART_MAP = {
'a_ip_address': 'a_part_ip_address',
'a_create_reverse': 'a_extra_create_reverse',
'aaaa_ip_address': 'aaaa_part_ip_address',
'aaaa_create_reverse': 'aaaa_extra_create_reverse',
'a6_data': 'a6_part_data',
'afsdb_subtype': 'afsdb_part_subtype',
'afsdb_hostname': 'afsdb_part_hostname',
'cert_type': 'cert_part_type',
'cert_key_tag': 'cert_part_key_tag',
'cert_algorithm': 'cert_part_algorithm',
'cert_certificate_or_crl': 'cert_part_certificate_or_crl',
'cname_hostname': 'cname_part_hostname',
'dlv_algorithm': 'dlv_part_algorithm',
'dlv_digest': 'dlv_part_digest',
'dlv_digest_type': 'dlv_part_digest_type',
'dlv_key_tag': 'dlv_part_key_tag',
'dname_target': 'dname_part_target',
'ds_algorithm': 'ds_part_algorithm',
'ds_digest': 'ds_part_digest',
'ds_digest_type': 'ds_part_digest_type',
'ds_key_tag': 'ds_part_key_tag',
'kx_preference': 'kx_part_preference',
'kx_exchanger': 'kx_part_exchanger',
"loc_lat_deg": "loc_part_lat_deg",
"loc_lat_min": "loc_part_lat_min",
"loc_lat_sec": "loc_part_lat_sec",
"loc_lat_dir": "loc_part_lat_dir",
"loc_lon_deg": "loc_part_lon_deg",
"loc_lon_min": "loc_part_lon_min",
"loc_lon_sec": "loc_part_lon_sec",
"loc_lon_dir": "loc_part_lon_dir",
"loc_altitude": "loc_part_altitude",
"loc_size": "loc_part_size",
"loc_h_precision": "loc_part_h_precision",
"loc_v_precision": "loc_part_v_precision",
"mx_preference": "mx_part_preference",
"mx_exchanger": 'mx_part_exchanger',
"naptr_order": "naptr_part_order",
"naptr_preference": "naptr_part_preference",
"naptr_flags": "naptr_part_flags",
"naptr_service": "naptr_part_service",
"naptr_regexp": "naptr_part_regexp",
"naptr_replacement": "naptr_part_replacement",
'ns_hostname': 'ns_part_hostname',
'ptr_hostname': 'ptr_part_hostname',
"srv_priority": "srv_part_priority",
"srv_weight": "srv_part_weight",
"srv_port": "srv_part_port",
"srv_target": "srv_part_target",
'sshfp_algorithm': 'sshfp_part_algorithm',
'sshfp_fingerprint': 'sshfp_part_fingerprint',
'sshfp_fp_type': 'sshfp_part_fp_type',
"tlsa_cert_usage": "tlsa_part_cert_usage",
"tlsa_cert_association_data": "tlsa_part_cert_association_data",
"tlsa_matching_type": "tlsa_part_matching_type",
"tlsa_selector": "tlsa_part_selector",
'txt_data': 'txt_part_data',
"uri_priority": "uri_part_priority",
"uri_target": "uri_part_target",
"uri_weight": "uri_part_weight"
}
# _RECORD_PARTS is a structure that maps the attributes that store
# the DNS record in FreeIPA API to the parts and options available
# for these records in the API.
_RECORD_PARTS = {
"arecord": ["a_part_ip_address", "a_extra_create_reverse"],
"aaaarecord": [
"aaaa_part_ip_address", "aaaa_extra_create_reverse"
],
"a6record": ["a6_part_data"],
"afsdbrecord": ['afsdb_part_subtype', 'afsdb_part_hostname'],
"certrecord": [
'cert_part_type', 'cert_part_key_tag', 'cert_part_algorithm',
'cert_part_certificate_or_crl'
],
"cnamerecord": ["cname_part_hostname"],
"dlvrecord": [
'dlv_part_key_tag', 'dlv_part_algorithm', 'dlv_part_digest_type',
'dlv_part_digest'
],
"dnamerecord": ["dname_part_target"],
"dsrecord": ['ds_part_key_tag', 'ds_part_algorithm',
'ds_part_digest_type', 'ds_part_digest'],
"kxrecord": ['kx_part_preference', 'kx_part_exchanger'],
"locrecord": [
"loc_part_lat_deg", "loc_part_lat_min", "loc_part_lat_sec",
"loc_part_lat_dir", "loc_part_lon_deg", "loc_part_lon_min",
"loc_part_lon_sec", "loc_part_lon_dir", "loc_part_altitude",
"loc_part_size", "loc_part_h_precision", "loc_part_v_precision"
],
"mxrecord": ['mx_part_preference', 'mx_part_exchanger'],
"naptrrecord": [
"naptr_part_order", "naptr_part_preference", "naptr_part_flags",
"naptr_part_service", "naptr_part_regexp", "naptr_part_replacement"
],
"nsrecord": ["ns_part_hostname"],
"ptrrecord": ["ptr_part_hostname"],
"srvrecord": [
"srv_part_priority", "srv_part_weight", "srv_part_port",
"srv_part_target",
],
"sshfprecord": [
'sshfp_part_algorithm', 'sshfp_part_fingerprint',
'sshfp_part_fp_type'
],
"tlsarecord": [
"tlsa_part_cert_usage", "tlsa_part_cert_association_data",
"tlsa_part_matching_type", "tlsa_part_selector"
],
"txtrecord": ["txt_part_data"],
"urirecord": ["uri_part_priority", "uri_part_target", "uri_part_weight"],
}
def configure_module():
"""Configure ipadnsrecord ansible module variables."""
record_spec = dict(
zone_name=dict(type='str', required=False, aliases=['dnszone']),
record_type=dict(type='str', default="A",
choices=["A", "AAAA", "A6", "AFSDB", "CERT", "CNAME",
"DLV", "DNAME", "DS", "KX", "LOC", "MX",
"NAPTR", "NS", "PTR", "SRV", "SSHFP", "TLSA",
"TXT", "URI"]),
record_value=dict(type='list', elements='str', required=False),
record_ttl=dict(type='int', required=False),
del_all=dict(type='bool', required=False),
a_rec=dict(type='list', elements='str', required=False,
aliases=['a_record']),
aaaa_rec=dict(type='list', elements='str', required=False,
aliases=['aaaa_record']),
a6_rec=dict(type='list', elements='str', required=False,
aliases=['a6_record']),
afsdb_rec=dict(type='list', elements='str', required=False,
aliases=['afsdb_record']),
cert_rec=dict(type='list', elements='str', required=False,
aliases=['cert_record']),
cname_rec=dict(type='list', elements='str', required=False,
aliases=['cname_record']),
dlv_rec=dict(type='list', elements='str', required=False,
aliases=['dlv_record']),
dname_rec=dict(type='list', elements='str', required=False,
aliases=['dname_record']),
ds_rec=dict(type='list', elements='str', required=False,
aliases=['ds_record']),
kx_rec=dict(type='list', elements='str', required=False,
aliases=['kx_record']),
loc_rec=dict(type='list', elements='str', required=False,
aliases=['loc_record']),
mx_rec=dict(type='list', elements='str', required=False,
aliases=['mx_record']),
naptr_rec=dict(type='list', elements='str', required=False,
aliases=['naptr_record']),
ns_rec=dict(type='list', elements='str', required=False,
aliases=['ns_record']),
ptr_rec=dict(type='list', elements='str', required=False,
aliases=['ptr_record']),
srv_rec=dict(type='list', elements='str', required=False,
aliases=['srv_record']),
sshfp_rec=dict(type='list', elements='str', required=False,
aliases=['sshfp_record']),
tlsa_rec=dict(type='list', elements='str', required=False,
aliases=['tlsa_record']),
txt_rec=dict(type='list', elements='str', required=False,
aliases=['txt_record']),
uri_rec=dict(type='list', elements='str', required=False,
aliases=['uri_record']),
ip_address=dict(type='str', required=False),
create_reverse=dict(type='bool', required=False, aliases=['reverse']),
a_ip_address=dict(type='str', required=False),
a_create_reverse=dict(type='bool', required=False),
aaaa_ip_address=dict(type='str', required=False),
aaaa_create_reverse=dict(type='bool', required=False),
a6_data=dict(type='str', required=False),
afsdb_subtype=dict(type='int', required=False),
afsdb_hostname=dict(type='str', required=False),
cert_type=dict(type='int', required=False),
cert_key_tag=dict(type='int', required=False, no_log=True),
cert_algorithm=dict(type='int', required=False),
cert_certificate_or_crl=dict(type='str', required=False),
cname_hostname=dict(type='str', required=False),
dlv_key_tag=dict(type='int', required=False, no_log=True),
dlv_algorithm=dict(type='int', required=False),
dlv_digest_type=dict(type='int', required=False),
dlv_digest=dict(type='str', required=False),
dname_target=dict(type='str', required=False),
ds_key_tag=dict(type='int', required=False, no_log=True),
ds_algorithm=dict(type='int', required=False),
ds_digest_type=dict(type='int', required=False),
ds_digest=dict(type='str', required=False),
kx_preference=dict(type='int', required=False),
kx_exchanger=dict(type='str', required=False),
loc_lat_deg=dict(type='int', required=False),
loc_lat_min=dict(type='int', required=False),
loc_lat_sec=dict(type='float', required=False),
loc_lat_dir=dict(type='str', required=False, choices=["N", "S"]),
loc_lon_deg=dict(type='int', required=False),
loc_lon_min=dict(type='int', required=False),
loc_lon_sec=dict(type='float', required=False),
loc_lon_dir=dict(type='str', required=False, choices=["E", "W"]),
loc_altitude=dict(type='float', required=False),
loc_size=dict(type='float', required=False),
loc_h_precision=dict(type='float', required=False),
loc_v_precision=dict(type='float', required=False),
mx_preference=dict(type='int', required=False),
mx_exchanger=dict(type='str', required=False),
naptr_order=dict(type='int', required=False),
naptr_preference=dict(type='int', required=False),
naptr_flags=dict(type='str', required=False),
naptr_service=dict(type='str', required=False),
naptr_regexp=dict(type='str', required=False),
naptr_replacement=dict(type='str', required=False),
ns_hostname=dict(type='str', required=False),
ptr_hostname=dict(type='str', required=False),
srv_priority=dict(type='int', required=False),
srv_weight=dict(type='int', required=False),
srv_port=dict(type='int', required=False),
srv_target=dict(type='str', required=False),
sshfp_algorithm=dict(type='int', required=False),
sshfp_fingerprint=dict(type='str', required=False),
sshfp_fp_type=dict(type='int', required=False),
tlsa_cert_usage=dict(type='int', required=False),
tlsa_cert_association_data=dict(type='str', required=False),
tlsa_matching_type=dict(type='int', required=False),
tlsa_selector=dict(type='int', required=False),
txt_data=dict(type='str', required=False),
uri_priority=dict(type='int', required=False),
uri_target=dict(type='str', required=False),
uri_weight=dict(type='int', required=False),
)
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["record_name"],
default=None, required=False),
# Use elements="str" and not elements="dict" for records:
# elements="dict" will create dicts with all unused parameters
# set to None. This breaks the module logic.
records=dict(type="list",
elements="dict",
default=None,
options=dict(
# Here name is a simple string
name=dict(type='str', required=True,
aliases=['record_name']),
**record_spec),
),
# general
state=dict(type="str", default="present",
choices=["present", "absent", "disabled"]),
# Add record specific parameters for simple use case
**record_spec
),
mutually_exclusive=[["name", "records"], ['record_value', 'del_all']],
required_one_of=[["name", "records"]],
supports_check_mode=True,
)
ansible_module._ansible_debug = True
if MODULE_IMPORT_ERROR is not None:
ansible_module.fail_json(msg=MODULE_IMPORT_ERROR)
return ansible_module
def find_dnsrecord(module, dnszone, name):
"""Find a DNS record based on its name (idnsname)."""
_args = {
"all": True,
"idnsname": to_text(name),
}
try:
_result = module.ipa_command(
"dnsrecord_show", to_text(dnszone), _args)
except ipalib_errors.NotFound:
return None
return _result["result"]
def check_parameters(module, state, zone_name, record):
"""Check if parameters are correct."""
if zone_name is None:
module.fail_json(msg="Msssing required argument: zone_name")
record_type = record.get('record_type', None)
record_value = record.get('record_value', None)
if record_type is not None:
if record_type not in _SUPPORTED_RECORD_TYPES:
module.fail_json(
msg="Record Type '%s' is not supported." % record_type)
# has_record is "True" if the playbook has set any of the full record
# attributes (*record or *_rec).
has_record = any(
(rec in record) or (("%sord" % rec) in record)
for rec in _RECORD_FIELDS
)
# has_part_record is "True" if the playbook has set any of the
# record field attributes.
has_part_record = any(record.get(rec, None) for rec in _PART_MAP)
# some attributes in the playbook may have a special meaning,
# like "ip_address", which is used for either arecord or aaaarecord,
# and has_special is true if any of these attributes is set on
# on the playbook.
special_list = ['ip_address']
has_special = any(record.get(rec, None) for rec in special_list)
invalid = []
if state == 'present':
if has_record or has_part_record or has_special:
if record_value:
module.fail_json(
msg="Cannot use record data with `record_value`.")
elif not record_value:
module.fail_json(msg="No record data provided.")
invalid = ['del_all']
if state == 'absent':
del_all = record.get('del_all', None)
if record_value:
if has_record or has_part_record or del_all:
module.fail_json(
msg="Cannot use record data with `record_value`.")
elif not (has_record or has_part_record or del_all):
module.fail_json(
msg="Either a record description or `del_all` is required.")
invalid = list(_PART_MAP.keys())
invalid.extend(['create_reverse', 'dns_ttl'])
module.params_fail_used_invalid(invalid, state)
def get_entry_from_module(module, name):
"""Create an entry dict from attributes in module."""
attrs = [
'del_all', 'zone_name', 'record_type', 'record_value', 'record_ttl',
"ip_address", "create_reverse"
]
entry = {'name': name}
for key_set in [_RECORD_FIELDS, _PART_MAP, attrs]:
entry.update({
key: module.params_get(key)
for key in key_set
if module.params_get(key) is not None
})
return entry
def create_reverse_ip_record(module, zone_name, name, ips):
"""Create a reverse record for an IP (PTR record)."""
_cmds = []
for address in ips:
reverse_ip = dns.reversename.from_address(address)
reverse_zone = dns.resolver.zone_for_name(reverse_ip)
reverse_host = to_text(reverse_ip).replace(".%s" % reverse_zone, '')
rev_find = find_dnsrecord(module, reverse_zone, reverse_host)
if rev_find is None:
rev_args = {
'idnsname': to_text(reverse_host),
"ptrrecord": "%s.%s" % (name, zone_name)
}
_cmds.append([to_text(reverse_zone), 'dnsrecord_add', rev_args])
return _cmds
def ensure_data_is_list(data):
"""Ensure data is represented as a list."""
return data if isinstance(data, list) else [data]
def gen_args(entry):
"""Generate IPA API arguments for a given `entry`."""
args = {'idnsname': to_text(entry['name'])}
if 'del_all' in entry:
args['del_all'] = entry['del_all']
record_value = entry.get('record_value', None)
if record_value is not None:
record_type = entry['record_type']
rec = "{0}record".format(record_type.lower())
args[rec] = ensure_data_is_list(record_value)
else:
for field in _RECORD_FIELDS:
record_value = entry.get(field) or entry.get("%sord" % field)
if record_value is not None:
# pylint: disable=use-maxsplit-arg
record_type = field.split('_')[0]
rec = "{0}record".format(record_type.lower())
args[rec] = ensure_data_is_list(record_value)
records = {
key: rec for key, rec in _PART_MAP.items() if key in entry
}
for key, rec in records.items():
args[rec] = entry[key]
if 'ip_address' in entry:
ip_address = entry['ip_address']
if is_ipv4_addr(ip_address):
args['a_part_ip_address'] = ip_address
if is_ipv6_addr(ip_address):
args['aaaa_part_ip_address'] = ip_address
if entry.get('create_reverse', False):
if 'a_part_ip_address' in args or 'arecord' in args:
args['a_extra_create_reverse'] = True
if 'aaaa_part_ip_address' in args or 'aaaarecord' in args:
args['aaaa_extra_create_reverse'] = True
if 'record_ttl' in entry:
args['dnsttl'] = entry['record_ttl']
return args
def define_commands_for_present_state(module, zone_name, entry, res_find):
"""Define commnads for `state: present`."""
_commands = []
name = to_text(entry['name'])
args = gen_args(entry)
existing = find_dnsrecord(module, zone_name, name)
for record, fields in _RECORD_PARTS.items():
part_fields = [f for f in fields if f in args]
if part_fields and record in args:
record_change_request = True
break
else:
record_change_request = False
if res_find is None and not record_change_request:
_commands.append([zone_name, 'dnsrecord_add', args])
else:
# Create reverse records for existing records
for ipv in ['a', 'aaaa']:
record = '%srecord' % ipv
if record in args and ('%s_extra_create_reverse' % ipv) in args:
cmds = create_reverse_ip_record(
module, zone_name, name, args[record])
_commands.extend(cmds)
del args['%s_extra_create_reverse' % ipv]
for record, fields in _RECORD_PARTS.items():
part_fields = [f for f in fields if f in args]
if part_fields:
if record in args:
# user wants to update record.
if len(args[record]) > 1:
module.fail_json(msg="Cannot modify multiple records "
"of the same type at once.")
mod_record = args[record][0]
if existing is None:
module.fail_json(msg="`%s` not found." % record)
else:
# update DNS record
_args = {k: args[k] for k in part_fields if k in args}
_args["idnsname"] = to_text(args["idnsname"])
_args[record] = mod_record
if 'dns_ttl' in args:
_args['dns_ttl'] = args['dns_ttl']
_commands.append([zone_name, 'dnsrecord_mod', _args])
# remove record from args, as it will not be used again.
del args[record]
else:
_args = {k: args[k] for k in part_fields if k in args}
_args['idnsname'] = name
_commands.append([zone_name, 'dnsrecord_add', _args])
# clean used fields from args
for f in part_fields: # pylint: disable=invalid-name
if f in args:
del args[f]
else:
if record in args:
add_list = []
for value in args[record]:
if (
res_find is None
or record not in res_find
or value not in res_find[record]
):
add_list.append(value)
if add_list:
args[record] = add_list
_commands.append([zone_name, 'dnsrecord_add', args])
return _commands
def define_commands_for_absent_state(module, zone_name, entry, res_find):
"""Define commands for `state: absent`."""
_commands = []
if res_find is None:
return []
args = gen_args(entry)
del_all = args.get('del_all', False)
records_to_delete = {k: v for k, v in args.items() if k.endswith('record')}
if del_all and records_to_delete:
module.fail_json(msg="Cannot use del_all and record together.")
if not del_all:
delete_records = False
for record, values in records_to_delete.items():
del_list = []
if record in res_find:
for value in values:
for rec_found in res_find[record]:
if rec_found == value:
del_list.append(value)
if del_list:
args[record] = del_list
delete_records = True
if delete_records:
_commands.append([zone_name, 'dnsrecord_del', args])
else:
_commands.append([zone_name, 'dnsrecord_del', args])
return _commands
# pylint: disable=unused-argument
def exception_handler(module, ex):
if isinstance(ex, (ipalib_errors.EmptyModlist,
ipalib_errors.DuplicateEntry)):
return True
return False
def main():
"""Execute DNS record playbook."""
ansible_module = configure_module()
global_zone_name = ansible_module.params_get("zone_name")
names = ansible_module.params_get("name")
records = ansible_module.params_get("records")
state = ansible_module.params_get("state")
# Check parameters
if (names is None or len(names) < 1) and \
(records is None or len(records) < 1):
ansible_module.fail_json(msg="One of name and records is required")
if state == "present":
if names is not None and len(names) != 1:
ansible_module.fail_json(
msg="Only one record can be added at a time.")
if records is not None:
# Remove all keys that have a None value from the dicts in records
# list.
# This is needed after setting elements="dict" for records and makes
# it behave like before with elements=None.
for record in records:
for key in list(record):
if record[key] is None:
del record[key]
names = records
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for record in names:
if isinstance(record, dict):
# ensure name is a string
zone_name = record.get("zone_name", global_zone_name)
name = record['name'] = str(record['name'])
entry = record
else:
zone_name = global_zone_name
name = record
entry = get_entry_from_module(ansible_module, name)
check_parameters(ansible_module, state, zone_name, entry)
res_find = find_dnsrecord(ansible_module, zone_name, name)
if state == 'present':
cmds = define_commands_for_present_state(
ansible_module, zone_name, entry, res_find)
elif state == 'absent':
cmds = define_commands_for_absent_state(
ansible_module, zone_name, entry, res_find)
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
if cmds:
commands.extend(cmds)
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, exception_handler=exception_handler)
# Done
ansible_module.exit_json(changed=changed, host=exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipadnszone.py 0000664 0000000 0000000 00000050320 14600563364 0023261 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Sergio Oliveira Campos
# Thomas Woerner
#
# Copyright (C) 2020-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipadnszone
short_description: Manage FreeIPA dnszone
description: Manage FreeIPA dnszone
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The zone name string.
required: false
type: list
elements: str
aliases: ["zone_name"]
name_from_ip:
description: |
Derive zone name from reverse of IP (PTR).
Can only be used with `state: present`.
required: false
type: str
forwarders:
description: The list of global DNS forwarders.
required: false
type: list
elements: dict
suboptions:
ip_address:
description: The forwarder nameserver IP address list (IPv4 and IPv6).
type: str
required: true
port:
description: The port to forward requests to.
type: int
required: false
forward_policy:
description:
Global forwarding policy. Set to "none" to disable any configured
global forwarders.
type: str
required: false
choices: ['only', 'first', 'none']
allow_sync_ptr:
description:
Allow synchronization of forward (A, AAAA) and reverse (PTR) records.
required: false
type: bool
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent", "enabled", "disabled"]
name_server:
description: Authoritative nameserver domain name
required: false
type: str
admin_email:
description: Administrator e-mail address
required: false
type: str
update_policy:
description: BIND update policy
required: false
type: str
dynamic_update:
description: Allow dynamic updates
required: false
type: bool
aliases: ["dynamicupdate"]
dnssec:
description: Allow inline DNSSEC signing of records in the zone
required: false
type: bool
allow_transfer:
description: List of IP addresses or networks which are allowed to transfer the zone
required: false
type: list
elements: str
allow_query:
description: List of IP addresses or networks which are allowed to issue queries
required: false
type: list
elements: str
refresh:
description: SOA record refresh time
required: false
type: int
retry:
description: SOA record retry time
required: false
type: int
expire:
description: SOA record expire time
required: false
type: int
minimum:
description: How long should negative responses be cached
required: false
type: int
ttl:
description: Time to live for records at zone apex
required: false
type: int
default_ttl:
description: Time to live for records without explicit TTL definition
required: false
type: int
nsec3param_rec:
description: |
NSEC3PARAM record for zone in format: hash_algorithm flags iterations
salt.
required: false
type: str
permission:
description: Set per-zone access delegation permission.
required: false
type: bool
aliases: ["managedby"]
skip_overlap_check:
description: |
Force DNS zone creation even if it will overlap with an existing zone
required: false
type: bool
skip_nameserver_check:
description: Force DNS zone creation even if nameserver is not resolvable
required: false
type: bool
author:
- Sergio Oliveira Campos (@seocam)
- Thomas Woerner (@t-woerner)
- Rafael Jeffman (@rjeffman)
""" # noqa: E501
EXAMPLES = """
---
# Ensure the zone is present (very minimal)
- ipadnszone:
name: test.example.com
# Ensure the zone is present (all available arguments)
- ipadnszone:
name: test.example.com
ipaadmin_password: SomeADMINpassword
allow_sync_ptr: true
dynamic_update: true
dnssec: true
allow_transfer:
- 1.1.1.1
- 2.2.2.2
allow_query:
- 1.1.1.1
- 2.2.2.2
forwarders:
- ip_address: 8.8.8.8
- ip_address: 8.8.4.4
port: 52
refresh: 3600
retry: 900
expire: 1209600
minimum: 3600
ttl: 60
default_ttl: 90
name_server: ipaserver.test.local.
admin_email: admin.admin@example.com
nsec3param_rec: "1 7 100 0123456789abcdef"
skip_overlap_check: true
skip_nameserver_check: true
state: present
# Ensure zone is present and disabled
- ipadnszone:
name: test.example.com
state: disabled
# Ensure zone is present and enabled
- ipadnszone:
name: test.example.com
state: enabled
"""
RETURN = """
dnszone:
description: DNS Zone dict with zone name infered from `name_from_ip`.
returned:
If `state` is `present`, `name_from_ip` is used, and a zone was created.
type: dict
contains:
name:
description: The name of the zone created, inferred from `name_from_ip`.
type: str
returned: always
"""
from ansible.module_utils.ansible_freeipa_module import (
IPAAnsibleModule,
is_ip_address,
is_ip_network_address,
is_valid_port,
ipalib_errors,
compare_args_ipa,
IPAParamMapping,
DNSName,
netaddr
) # noqa: E402
from ansible.module_utils import six
if six.PY3:
unicode = str
class DNSZoneModule(IPAAnsibleModule):
def __init__(self, *args, **kwargs):
# pylint: disable=super-with-arguments
super(DNSZoneModule, self).__init__(*args, **kwargs)
ipa_param_mapping = {
# Direct Mapping
"idnsforwardpolicy": "forward_policy",
"idnssoarefresh": "refresh",
"idnssoaretry": "retry",
"idnssoaexpire": "expire",
"idnssoaminimum": "minimum",
"dnsttl": "ttl",
"dnsdefaultttl": "default_ttl",
"idnsallowsyncptr": "allow_sync_ptr",
"idnsallowdynupdate": "dynamic_update",
"idnssecinlinesigning": "dnssec",
"idnsupdatepolicy": "update_policy",
# FreeIPA uses 'managedby' for dnszone and dnsforwardzone
# to manage 'permissions'.
"managedby": "permission",
# Mapping by method
"idnsforwarders": self.get_ipa_idnsforwarders,
"idnsallowtransfer": self.get_ipa_idnsallowtransfer,
"idnsallowquery": self.get_ipa_idnsallowquery,
"idnssoamname": self.get_ipa_idnssoamname,
"idnssoarname": self.get_ipa_idnssoarname,
"skip_nameserver_check": self.get_ipa_skip_nameserver_check,
"skip_overlap_check": self.get_ipa_skip_overlap_check,
"nsec3paramrecord": self.get_ipa_nsec3paramrecord,
}
self.commands = []
self.ipa_params = IPAParamMapping(self, ipa_param_mapping)
self.exit_args = {}
def validate_ips(self, ips, error_msg):
invalid_ips = [
ip for ip in ips
if not any([
is_ip_address(ip),
is_ip_network_address(ip),
ip in ["any", "localhost", "localnets", "none"]
])
]
if any(invalid_ips):
self.fail_json(msg=error_msg % invalid_ips)
@staticmethod
def is_valid_nsec3param_rec(nsec3param_rec):
try:
part1, part2, part3, part4 = nsec3param_rec.split(" ")
except ValueError:
return False
if (
not all([part1.isdigit(), part2.isdigit(), part3.isdigit()])
or not 0 <= int(part1) <= 255
or not 0 <= int(part2) <= 255
or not 0 <= int(part3) <= 65535
):
return False
try:
int(part4, 16)
except ValueError:
is_hex = False
else:
is_hex = True
even_digits = len(part4) % 2 == 0
is_dash = part4 == "-"
# If not hex with even digits or dash then
# part4 is invalid
if not ((is_hex and even_digits) or is_dash):
return False
return True
def get_ipa_nsec3paramrecord(self, **_kwargs): # pylint: disable=R1710
nsec3param_rec = self.ipa_params.nsec3param_rec
if nsec3param_rec is not None:
error_msg = (
"Invalid nsec3param_rec: %s. "
"Expected format: <0-255> <0-255> <0-65535> "
"even-length_hexadecimal_digits_or_hyphen"
) % nsec3param_rec
if not self.is_valid_nsec3param_rec(nsec3param_rec):
self.fail_json(msg=error_msg)
return nsec3param_rec
def get_ipa_idnsforwarders(self, **_kwargs): # pylint: disable=R1710
if self.ipa_params.forwarders is not None:
forwarders = []
for forwarder in self.ipa_params.forwarders:
ip_address = forwarder.get("ip_address")
if not is_ip_address(ip_address):
self.fail_json(
msg="Invalid IP for DNS forwarder: %s" % ip_address
)
port = forwarder.get("port", None)
if port and not is_valid_port(port):
self.fail_json(
msg="Invalid port number for DNS forwarder: %s %s"
% (ip_address, port)
)
formatted_forwarder = ip_address
port = forwarder.get("port")
if port:
formatted_forwarder += " port %d" % port
forwarders.append(formatted_forwarder)
return forwarders
def get_ipa_idnsallowtransfer(self, **_kwargs): # pylint: disable=R1710
if self.ipa_params.allow_transfer is not None:
error_msg = "Invalid ip_address for DNS allow_transfer: %s"
self.validate_ips(self.ipa_params.allow_transfer, error_msg)
return (";".join(self.ipa_params.allow_transfer) or "none") + ";"
def get_ipa_idnsallowquery(self, **_kwargs): # pylint: disable=R1710
if self.ipa_params.allow_query is not None:
error_msg = "Invalid ip_address for DNS allow_query: %s"
self.validate_ips(self.ipa_params.allow_query, error_msg)
return (";".join(self.ipa_params.allow_query) or "any") + ";"
@staticmethod
def _replace_at_symbol_in_rname(rname):
"""
See RFC 1035 for more information.
Section 8. MAIL SUPPORT
https://tools.ietf.org/html/rfc1035#section-8
"""
if "@" not in rname:
return rname
name, domain = rname.split("@")
name = name.replace(".", r"\.")
return ".".join((name, domain))
def get_ipa_idnssoarname(self, **_kwargs): # pylint: disable=R1710
if self.ipa_params.admin_email is not None:
return DNSName(
self._replace_at_symbol_in_rname(self.ipa_params.admin_email)
)
def get_ipa_idnssoamname(self, **_kwargs): # pylint: disable=R1710
if self.ipa_params.name_server is not None:
return DNSName(self.ipa_params.name_server)
def get_ipa_skip_overlap_check(self, **kwargs): # pylint: disable=R1710
zone = kwargs.get('zone')
if not zone and self.ipa_params.skip_overlap_check is not None:
return self.ipa_params.skip_overlap_check
def get_ipa_skip_nameserver_check(self, **kwargs): # pylint: disable=R1710
zone = kwargs.get('zone')
if not zone and self.ipa_params.skip_nameserver_check is not None:
return self.ipa_params.skip_nameserver_check
def __reverse_zone_name(self, ipaddress): # pylint: disable=R1710
"""
Infer reverse zone name from an ip address.
This function uses the same heuristics as FreeIPA to infer the zone
name from ip.
"""
try:
ip = netaddr.IPAddress(str(ipaddress))
except (netaddr.AddrFormatError, ValueError):
net = netaddr.IPNetwork(ipaddress)
items = net.ip.reverse_dns.split('.')
prefixlen = net.prefixlen
ip_version = net.version
else:
items = ip.reverse_dns.split('.')
prefixlen = 24 if ip.version == 4 else 64
ip_version = ip.version
if ip_version == 4:
return u'.'.join(items[4 - prefixlen // 8:])
if ip_version == 6:
return u'.'.join(items[32 - prefixlen // 4:])
self.fail_json(msg="Invalid IP version for reverse zone.")
def get_zone(self, zone_name):
get_zone_args = {"idnsname": zone_name, "all": True}
try:
response = self.ipa_command_no_name(
"dnszone_show", args=get_zone_args
)
except ipalib_errors.NotFound:
zone = None
is_zone_active = False
else:
zone = response["result"]
# FreeIPA 4.9.10+ and 4.10 use proper mapping for boolean values.
# See: https://github.com/freeipa/freeipa/pull/6294
is_zone_active = (
str(zone.get("idnszoneactive")[0]).upper() == "TRUE"
)
return zone, is_zone_active
def get_zone_names(self):
zone_names = self.__get_zone_names_from_params()
if len(zone_names) > 1 and self.ipa_params.state != "absent":
self.fail_json(
msg=("Please provide a single name. Multiple values for 'name'"
"can only be supplied for state 'absent'.")
)
return zone_names
def __get_zone_names_from_params(self):
if not self.ipa_params.name:
return [self.__reverse_zone_name(self.ipa_params.name_from_ip)]
return self.ipa_params.name
def check_ipa_params(self):
if not self.ipa_params.name and not self.ipa_params.name_from_ip:
self.fail_json(
msg="Either `name` or `name_from_ip` must be provided."
)
# check invalid parameters
invalid = []
if self.ipa_params.state != "present":
invalid .extend(["name_from_ip"])
if self.ipa_params.state == "absent":
invalid.extend(["permission"])
self.params_fail_used_invalid(invalid, self.ipa_params.state)
def define_ipa_commands(self):
for zone_name in self.get_zone_names():
# Look for existing zone in IPA
zone, is_zone_active = self.get_zone(zone_name)
if self.ipa_params.state in ["present", "enabled", "disabled"]:
args = self.ipa_params.get_ipa_command_args(zone=zone)
# We'll handle "managedby" after dnszone add/mod.
args.pop("managedby", None)
if not zone:
# Since the zone doesn't exist we just create it
# with given args
self.commands.append((zone_name, "dnszone_add", args))
is_zone_active = True
# just_added = True
else:
# Zone already exist so we need to verify if given args
# matches the current config. If not we updated it.
if not compare_args_ipa(self, args, zone):
self.commands.append((zone_name, "dnszone_mod", args))
# Permissions must be set on existing zones.
if self.ipa_params.permission is not None:
is_managed = zone.get("managedby")
if self.ipa_params.permission and not is_managed:
self.commands.append(
(zone_name, "dnszone_add_permission", {}))
if not self.ipa_params.permission and is_managed:
self.commands.append(
(zone_name, "dnszone_remove_permission", {}))
if self.ipa_params.state == "enabled" and not is_zone_active:
self.commands.append((zone_name, "dnszone_enable", {}))
if self.ipa_params.state == "disabled" and is_zone_active:
self.commands.append((zone_name, "dnszone_disable", {}))
if self.ipa_params.state == "absent" and zone is not None:
self.commands.append((zone_name, "dnszone_del", {}))
def process_results(self, _result, command, name, _args, exit_args):
if command == "dnszone_add" and self.ipa_params.name_from_ip:
exit_args.setdefault('dnszone', {})["name"] = name
def get_argument_spec():
forwarder_spec = dict(
ip_address=dict(type="str", required=True),
port=dict(type="int", required=False, default=None),
)
return dict(
state=dict(
type="str",
default="present",
choices=["present", "absent", "enabled", "disabled"],
),
ipaadmin_principal=dict(type="str", default="admin"),
ipaadmin_password=dict(type="str", required=False, no_log=True),
name=dict(
type="list", elements="str", default=None, required=False,
aliases=["zone_name"]
),
name_from_ip=dict(type="str", default=None, required=False),
forwarders=dict(
type="list",
elements="dict",
default=None,
required=False,
options=dict(**forwarder_spec),
),
forward_policy=dict(
type="str",
required=False,
default=None,
choices=["only", "first", "none"],
),
name_server=dict(type="str", required=False, default=None),
admin_email=dict(type="str", required=False, default=None),
allow_sync_ptr=dict(type="bool", required=False, default=None),
update_policy=dict(type="str", required=False, default=None),
dynamic_update=dict(
type="bool",
required=False,
default=None,
aliases=["dynamicupdate"],
),
dnssec=dict(type="bool", required=False, default=None),
allow_transfer=dict(type="list", elements="str", required=False,
default=None),
allow_query=dict(type="list", elements="str", required=False,
default=None),
refresh=dict(type="int", required=False, default=None),
retry=dict(type="int", required=False, default=None),
expire=dict(type="int", required=False, default=None),
minimum=dict(type="int", required=False, default=None),
ttl=dict(type="int", required=False, default=None),
default_ttl=dict(type="int", required=False, default=None),
nsec3param_rec=dict(type="str", required=False, default=None),
permission=dict(type="bool", required=False, default=None,
aliases=["managedby"]),
skip_nameserver_check=dict(type="bool", required=False, default=None),
skip_overlap_check=dict(type="bool", required=False, default=None),
)
def main():
ansible_module = DNSZoneModule(
argument_spec=get_argument_spec(),
mutually_exclusive=[["name", "name_from_ip"]],
required_one_of=[["name", "name_from_ip"]],
supports_check_mode=True,
)
exit_args = {}
ipaapi_context = ansible_module.params_get("ipaapi_context")
with ansible_module.ipa_connect(context=ipaapi_context):
ansible_module.check_ipa_params()
ansible_module.define_ipa_commands()
changed = ansible_module.execute_ipa_commands(
ansible_module.commands,
result_handler=DNSZoneModule.process_results,
exit_args=exit_args
)
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipagroup.py 0000664 0000000 0000000 00000077327 14600563364 0022755 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipagroup
short_description: Manage FreeIPA groups
description: Manage FreeIPA groups
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The group name
type: list
elements: str
required: false
aliases: ["cn"]
groups:
description: The list of group dicts (internally gid).
type: list
elements: dict
suboptions:
name:
description: The group (internally gid).
type: str
required: true
aliases: ["cn"]
description:
description: The group description
type: str
required: false
gid:
description: The GID
type: int
required: false
aliases: ["gidnumber"]
nonposix:
description: Create as a non-POSIX group
required: false
type: bool
external:
description: Allow adding external non-IPA members from trusted domains
required: false
type: bool
posix:
description:
Create a non-POSIX group or change a non-POSIX to a posix group.
required: false
type: bool
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
user:
description: List of user names assigned to this group.
required: false
type: list
elements: str
group:
description: List of group names assigned to this group.
required: false
type: list
elements: str
service:
description:
- List of service names assigned to this group.
- Only usable with IPA versions 4.7 and up.
required: false
type: list
elements: str
membermanager_user:
description:
- List of member manager users assigned to this group.
- Only usable with IPA versions 4.8.4 and up.
required: false
type: list
elements: str
membermanager_group:
description:
- List of member manager groups assigned to this group.
- Only usable with IPA versions 4.8.4 and up.
required: false
type: list
elements: str
externalmember:
description:
- List of members of a trusted domain in DOM\\name or name@domain form.
required: false
type: list
elements: str
aliases: ["ipaexternalmember", "external_member"]
idoverrideuser:
description:
- User ID overrides to add
required: false
type: list
elements: str
rename:
description: Rename the group object
required: false
type: str
aliases: ["new_name"]
description:
description: The group description
type: str
required: false
gid:
description: The GID
type: int
required: false
aliases: ["gidnumber"]
nonposix:
description: Create as a non-POSIX group
required: false
type: bool
external:
description: Allow adding external non-IPA members from trusted domains
required: false
type: bool
posix:
description:
Create a non-POSIX group or change a non-POSIX to a posix group.
required: false
type: bool
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
user:
description: List of user names assigned to this group.
required: false
type: list
elements: str
group:
description: List of group names assigned to this group.
required: false
type: list
elements: str
service:
description:
- List of service names assigned to this group.
- Only usable with IPA versions 4.7 and up.
required: false
type: list
elements: str
membermanager_user:
description:
- List of member manager users assigned to this group.
- Only usable with IPA versions 4.8.4 and up.
required: false
type: list
elements: str
membermanager_group:
description:
- List of member manager groups assigned to this group.
- Only usable with IPA versions 4.8.4 and up.
required: false
type: list
elements: str
externalmember:
description:
- List of members of a trusted domain in DOM\\name or name@domain form.
required: false
type: list
elements: str
aliases: ["ipaexternalmember", "external_member"]
idoverrideuser:
description:
- User ID overrides to add
required: false
type: list
elements: str
action:
description: Work on group or member level
type: str
default: group
choices: ["member", "group"]
rename:
description: Rename the group object
required: false
type: str
aliases: ["new_name"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent", "renamed"]
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Create group ops with gid 1234
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: ops
gidnumber: 1234
# Create group sysops
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: sysops
# Create group appops
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: appops
# Create multiple groups ops, sysops
- ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: ops
gidnumber: 1234
- name: sysops
# Add user member pinky to group sysops
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: sysops
action: member
user:
- pinky
# Add user member brain to group sysops
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: sysops
action: member
user:
- brain
# Add group members sysops and appops to group ops
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: ops
group:
- sysops
- appops
# Add user and group members to groups sysops and appops
- ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: sysops
user:
- user1
- name: appops
group:
- group2
# Rename a group
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: oldname
rename: newestname
state: renamed
# Create a non-POSIX group
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: nongroup
nonposix: yes
# Turn a non-POSIX group into a POSIX group.
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: nonposix
posix: yes
# Create an external group and add members from a trust to it.
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external: yes
externalmember:
- WINIPA\\Web Users
- WINIPA\\Developers
# Create multiple non-POSIX and external groups
- ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: nongroup
nonposix: true
- name: extgroup
external: true
# Remove groups sysops, appops, ops and nongroup
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: sysops,appops,ops, nongroup
state: absent
"""
RETURN = """
"""
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, \
gen_add_list, gen_intersection_list, api_check_param
from ansible.module_utils import six
if six.PY3:
unicode = str
# Ensuring (adding) several groups with mixed types external, nonposix
# and posix require to have a fix in IPA:
# FreeIPA issue: https://pagure.io/freeipa/issue/9349
# FreeIPA fix: https://github.com/freeipa/freeipa/pull/6741
try:
from ipaserver.plugins import baseldap
except ImportError:
FIX_6741_DEEPCOPY_OBJECTCLASSES = False
else:
FIX_6741_DEEPCOPY_OBJECTCLASSES = \
"deepcopy" in baseldap.LDAPObject.__json__.__code__.co_names
def find_group(module, name):
_args = {
"all": True,
"cn": name,
}
_result = module.ipa_command("group_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one group '%s'" % (name))
elif len(_result["result"]) == 1:
_res = _result["result"][0]
# The returned services are of type ipapython.kerberos.Principal,
# also services are not case sensitive. Therefore services are
# converted to lowercase strings to be able to do the comparison.
if "member_service" in _res:
_res["member_service"] = \
[to_text(svc).lower() for svc in _res["member_service"]]
return _res
return None
def gen_args(description, gid, nomembers):
_args = {}
if description is not None:
_args["description"] = description
if gid is not None:
_args["gidnumber"] = gid
if nomembers is not None:
_args["nomembers"] = nomembers
return _args
def gen_member_args(user, group, service, externalmember, idoverrideuser):
_args = {}
if user is not None:
_args["member_user"] = user
if group is not None:
_args["member_group"] = group
if service is not None:
_args["member_service"] = service
if externalmember is not None:
_args["member_external"] = externalmember
if idoverrideuser is not None:
_args["member_idoverrideuser"] = idoverrideuser
return _args
def check_parameters(module, state, action):
invalid = ["description", "gid", "posix", "nonposix", "external",
"nomembers"]
if action == "group":
if state == "present":
invalid = []
elif state == "absent":
invalid.extend(["user", "group", "service", "externalmember"])
if state == "renamed":
if action == "member":
module.fail_json(
msg="Action member can not be used with state: renamed.")
invalid.extend(["user", "group", "service", "externalmember"])
else:
invalid.append("rename")
module.params_fail_used_invalid(invalid, state, action)
def is_external_group(res_find):
"""Verify if the result group is an external group."""
return res_find and 'ipaexternalgroup' in res_find['objectclass']
def is_posix_group(res_find):
"""Verify if the result group is an posix group."""
return res_find and 'posixgroup' in res_find['objectclass']
def check_objectclass_args(module, res_find, posix, external):
# Only a nonposix group can be changed to posix or external
# A posix group can not be changed to nonposix or external
if is_posix_group(res_find):
if external is not None and external or posix is False:
module.fail_json(
msg="Cannot change `posix` group to `non-posix` or "
"`external`.")
# An external group can not be changed to nonposix or posix or nonexternal
if is_external_group(res_find):
if external is False or posix is not None:
module.fail_json(
msg="Cannot change `external` group to `posix` or "
"`non-posix`.")
def main():
group_spec = dict(
# present
description=dict(type="str", default=None),
gid=dict(type="int", aliases=["gidnumber"], default=None),
nonposix=dict(required=False, type='bool', default=None),
external=dict(required=False, type='bool', default=None),
posix=dict(required=False, type='bool', default=None),
nomembers=dict(required=False, type='bool', default=None),
user=dict(required=False, type='list', elements="str",
default=None),
group=dict(required=False, type='list', elements="str",
default=None),
service=dict(required=False, type='list', elements="str",
default=None),
idoverrideuser=dict(required=False, type='list', elements="str",
default=None),
membermanager_user=dict(required=False, type='list',
elements="str", default=None),
membermanager_group=dict(required=False, type='list',
elements="str", default=None),
externalmember=dict(required=False, type='list', elements="str",
default=None,
aliases=[
"ipaexternalmember",
"external_member"
]),
rename=dict(type="str", required=False, default=None,
aliases=["new_name"]),
)
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
default=None, required=False),
groups=dict(type="list",
default=None,
options=dict(
# Here name is a simple string
name=dict(type="str", required=True,
aliases=["cn"]),
# Add group specific parameters
**group_spec
),
elements='dict',
required=False),
# general
action=dict(type="str", default="group",
choices=["member", "group"]),
state=dict(type="str", default="present",
choices=["present", "absent", "renamed"]),
# Add group specific parameters for simple use case
**group_spec
),
# It does not make sense to set posix, nonposix or external at the
# same time
mutually_exclusive=[['posix', 'nonposix', 'external'],
["name", "groups"]],
required_one_of=[["name", "groups"]],
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
groups = ansible_module.params_get("groups")
# present
description = ansible_module.params_get("description")
gid = ansible_module.params_get("gid")
nonposix = ansible_module.params_get("nonposix")
external = ansible_module.params_get("external")
idoverrideuser = ansible_module.params_get("idoverrideuser")
posix = ansible_module.params_get("posix")
nomembers = ansible_module.params_get("nomembers")
user = ansible_module.params_get_lowercase("user")
group = ansible_module.params_get_lowercase("group")
# Services are not case sensitive
service = ansible_module.params_get_lowercase("service")
membermanager_user = (
ansible_module.params_get_lowercase("membermanager_user"))
membermanager_group = (
ansible_module.params_get_lowercase("membermanager_group"))
externalmember = ansible_module.params_get("externalmember")
# rename
rename = ansible_module.params_get("rename")
# state and action
action = ansible_module.params_get("action")
state = ansible_module.params_get("state")
# Check parameters
if (names is None or len(names) < 1) and \
(groups is None or len(groups) < 1):
ansible_module.fail_json(msg="At least one name or groups is required")
if state in ["present", "renamed"]:
if names is not None and len(names) != 1:
what = "renamed" if state == "renamed" else "added"
ansible_module.fail_json(
msg="Only one group can be %s at a time using 'name'." % what)
check_parameters(ansible_module, state, action)
if external is False:
ansible_module.fail_json(
msg="group can not be non-external")
# Ensuring (adding) several groups with mixed types external, nonposix
# and posix require to have a fix in IPA:
#
# FreeIPA issue: https://pagure.io/freeipa/issue/9349
# FreeIPA fix: https://github.com/freeipa/freeipa/pull/6741
#
# The simple solution is to switch to client context for ensuring
# several groups simply if the user was not explicitly asking for
# the server context no matter if mixed types are used.
context = None
if state == "present" and groups is not None and len(groups) > 1 \
and not FIX_6741_DEEPCOPY_OBJECTCLASSES:
_context = ansible_module.params_get("ipaapi_context")
if _context is None:
context = "client"
ansible_module.debug(
"Switching to client context due to an unfixed issue in "
"your IPA version: https://pagure.io/freeipa/issue/9349")
elif _context == "server":
ansible_module.fail_json(
msg="Ensuring several groups with server context is not "
"supported by your IPA version: "
"https://pagure.io/freeipa/issue/9349")
# Use groups if names is None
if groups is not None:
names = groups
# Init
changed = False
exit_args = {}
# If nonposix is used, set posix as not nonposix
if nonposix is not None:
posix = not nonposix
# Connect to IPA API
with ansible_module.ipa_connect(context=context):
has_add_member_service = ansible_module.ipa_command_param_exists(
"group_add_member", "service")
if service is not None and not has_add_member_service:
ansible_module.fail_json(
msg="Managing a service as part of a group is not supported "
"by your IPA version")
has_add_membermanager = ansible_module.ipa_command_exists(
"group_add_member_manager")
if ((membermanager_user is not None or
membermanager_group is not None) and not has_add_membermanager):
ansible_module.fail_json(
msg="Managing a membermanager user or group is not supported "
"by your IPA version"
)
has_idoverrideuser = api_check_param(
"group_add_member", "idoverrideuser")
if idoverrideuser is not None and not has_idoverrideuser:
ansible_module.fail_json(
msg="Managing a idoverrideuser as part of a group is not "
"supported by your IPA version")
commands = []
group_set = set()
for group_name in names:
if isinstance(group_name, dict):
name = group_name.get("name")
if name in group_set:
ansible_module.fail_json(
msg="group '%s' is used more than once" % name)
group_set.add(name)
# present
description = group_name.get("description")
gid = group_name.get("gid")
nonposix = group_name.get("nonposix")
external = group_name.get("external")
idoverrideuser = group_name.get("idoverrideuser")
posix = group_name.get("posix")
# Check mutually exclusive condition for multiple groups
# creation. It's not possible to check it with
# `mutually_exclusive` argument in `IPAAnsibleModule` class
# because it accepts only (list[str] or list[list[str]]). Here
# we need to loop over all groups and fail on mutually
# exclusive ones.
if all((posix, nonposix)) or\
all((posix, external)) or\
all((nonposix, external)):
ansible_module.fail_json(
msg="parameters are mutually exclusive for group "
"`{0}`: posix|nonposix|external".format(name))
# Duplicating the condition for multiple group creation
if external is False:
ansible_module.fail_json(
msg="group can not be non-external")
# If nonposix is used, set posix as not nonposix
if nonposix is not None:
posix = not nonposix
user = group_name.get("user")
group = group_name.get("group")
service = group_name.get("service")
membermanager_user = group_name.get("membermanager_user")
membermanager_group = group_name.get("membermanager_group")
externalmember = group_name.get("externalmember")
nomembers = group_name.get("nomembers")
rename = group_name.get("rename")
check_parameters(ansible_module, state, action)
elif isinstance(group_name, (str, unicode)):
name = group_name
else:
ansible_module.fail_json(msg="Group '%s' is not valid" %
repr(group_name))
# Make sure group exists
res_find = find_group(ansible_module, name)
user_add, user_del = [], []
group_add, group_del = [], []
service_add, service_del = [], []
externalmember_add, externalmember_del = [], []
idoverrides_add, idoverrides_del = [], []
membermanager_user_add, membermanager_user_del = [], []
membermanager_group_add, membermanager_group_del = [], []
# Create command
if state == "present":
# Can't change an existing posix group
check_objectclass_args(ansible_module, res_find, posix,
external)
# Generate args
args = gen_args(description, gid, nomembers)
if action == "group":
# Found the group
if res_find is not None:
# For all settings in args, check if there are
# different settings in the find result.
# If yes: modify
# Also if it is a modification from nonposix to posix
# or nonposix to external.
if not compare_args_ipa(
ansible_module, args, res_find
) or (
not is_posix_group(res_find) and
not is_external_group(res_find) and
(posix or external)
):
if posix:
args['posix'] = True
if external:
args['external'] = True
commands.append([name, "group_mod", args])
else:
if posix is not None and not posix:
args['nonposix'] = True
if external:
args['external'] = True
commands.append([name, "group_add", args])
# Set res_find dict for next step
res_find = {}
# if we just created/modified the group, update res_find
res_find.setdefault("objectclass", [])
if external and not is_external_group(res_find):
res_find["objectclass"].append("ipaexternalgroup")
if posix and not is_posix_group(res_find):
res_find["objectclass"].append("posixgroup")
member_args = gen_member_args(
user, group, service, externalmember, idoverrideuser
)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
user_add, user_del = gen_add_del_lists(
user, res_find.get("member_user"))
group_add, group_del = gen_add_del_lists(
group, res_find.get("member_group"))
service_add, service_del = gen_add_del_lists(
service, res_find.get("member_service"))
(externalmember_add,
externalmember_del) = gen_add_del_lists(
externalmember, res_find.get("member_external"))
(idoverrides_add,
idoverrides_del) = gen_add_del_lists(
idoverrideuser,
res_find.get("member_idoverrideuser")
)
membermanager_user_add, membermanager_user_del = \
gen_add_del_lists(
membermanager_user,
res_find.get("membermanager_user")
)
membermanager_group_add, membermanager_group_del = \
gen_add_del_lists(
membermanager_group,
res_find.get("membermanager_group")
)
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No group '%s'" % name)
# Reduce add lists for member_user, member_group,
# member_service and member_external to new entries
# only that are not in res_find.
user_add = gen_add_list(
user, res_find.get("member_user"))
group_add = gen_add_list(
group, res_find.get("member_group"))
service_add = gen_add_list(
service, res_find.get("member_service"))
externalmember_add = gen_add_list(
externalmember, res_find.get("member_external"))
idoverrides_add = gen_add_list(
idoverrideuser, res_find.get("member_idoverrideuser"))
membermanager_user_add = gen_add_list(
membermanager_user,
res_find.get("membermanager_user")
)
membermanager_group_add = gen_add_list(
membermanager_group,
res_find.get("membermanager_group")
)
elif state == "absent":
if action == "group":
if res_find is not None:
commands.append([name, "group_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No group '%s'" % name)
if not is_external_group(res_find) and externalmember:
ansible_module.fail_json(
msg="Cannot add external members to a "
"non-external group."
)
user_del = gen_intersection_list(
user, res_find.get("member_user"))
group_del = gen_intersection_list(
group, res_find.get("member_group"))
service_del = gen_intersection_list(
service, res_find.get("member_service"))
externalmember_del = gen_intersection_list(
externalmember, res_find.get("member_external"))
idoverrides_del = gen_intersection_list(
idoverrideuser, res_find.get("member_idoverrideuser"))
membermanager_user_del = gen_intersection_list(
membermanager_user, res_find.get("membermanager_user"))
membermanager_group_del = gen_intersection_list(
membermanager_group,
res_find.get("membermanager_group")
)
elif state == "renamed":
if res_find is None:
ansible_module.fail_json(msg="No group '%s'" % name)
elif rename != name:
commands.append([name, 'group_mod', {"rename": rename}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# manage members
# setup member args for add/remove members.
add_member_args = {
"user": user_add,
"group": group_add,
}
del_member_args = {
"user": user_del,
"group": group_del,
}
if has_idoverrideuser:
add_member_args["idoverrideuser"] = idoverrides_add
del_member_args["idoverrideuser"] = idoverrides_del
if has_add_member_service:
add_member_args["service"] = service_add
del_member_args["service"] = service_del
if is_external_group(res_find):
if len(externalmember_add) > 0:
add_member_args["ipaexternalmember"] = \
externalmember_add
if len(externalmember_del) > 0:
del_member_args["ipaexternalmember"] = \
externalmember_del
elif externalmember or external:
ansible_module.fail_json(
msg="Cannot add external members to a "
"non-external group."
)
# Add members
add_members = any([user_add, group_add, idoverrides_add,
service_add, externalmember_add])
if add_members:
commands.append(
[name, "group_add_member", add_member_args]
)
# Remove members
remove_members = any([user_del, group_del, idoverrides_del,
service_del, externalmember_del])
if remove_members:
commands.append(
[name, "group_remove_member", del_member_args]
)
# manage membermanager members
if has_add_membermanager:
# Add membermanager users and groups
if any([membermanager_user_add, membermanager_group_add]):
commands.append(
[name, "group_add_member_manager",
{
"user": membermanager_user_add,
"group": membermanager_group_add,
}]
)
# Remove member manager
if any([membermanager_user_del, membermanager_group_del]):
commands.append(
[name, "group_remove_member_manager",
{
"user": membermanager_user_del,
"group": membermanager_group_del,
}]
)
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipahbacrule.py 0000664 0000000 0000000 00000054021 14600563364 0023370 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipahbacrule
short_description: Manage FreeIPA HBAC rules
description: Manage FreeIPA HBAC rules
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The hbacrule name
type: list
elements: str
required: true
aliases: ["cn"]
description:
description: The hbacrule description
type: str
required: false
usercategory:
description: User category the rule applies to
type: str
required: false
aliases: ["usercat"]
choices: ["all", ""]
hostcategory:
description: Host category the rule applies to
type: str
required: false
aliases: ["hostcat"]
choices: ["all", ""]
servicecategory:
description: Service category the rule applies to
type: str
required: false
aliases: ["servicecat"]
choices: ["all", ""]
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
host:
description: List of host names assigned to this hbacrule.
required: false
type: list
elements: str
hostgroup:
description: List of host groups assigned to this hbacrule.
required: false
type: list
elements: str
hbacsvc:
description: List of HBAC service names assigned to this hbacrule.
required: false
type: list
elements: str
hbacsvcgroup:
description: List of HBAC service names assigned to this hbacrule.
required: false
type: list
elements: str
user:
description: List of user names assigned to this hbacrule.
required: false
type: list
elements: str
group:
description: List of user groups assigned to this hbacrule.
required: false
type: list
elements: str
action:
description: Work on hbacrule or member level
type: str
default: hbacrule
choices: ["member", "hbacrule"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent", "enabled", "disabled"]
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure HBAC Rule allhosts is present
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allhosts
usercategory: all
# Ensure host server is present in HBAC Rule allhosts
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allhosts
host: server
action: member
# Ensure HBAC Rule sshd-pinky is present
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: sshd-pinky
hostcategory: all
# Ensure user pinky is present in HBAC Rule sshd-pinky
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: sshd-pinky
user: pinky
action: member
# Ensure HBAC service sshd is present in HBAC Rule sshd-pinky
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: sshd-pinky
hbacsvc: sshd
action: member
# Ensure HBAC Rule sshd-pinky is disabled
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: sshd-pinky
state: disabled
# Ensure HBAC Rule sshd-pinky is enabled
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: sshd-pinky
state: enabled
# Ensure HBAC Rule sshd-pinky is absent
- ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: sshd-pinky
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
gen_intersection_list, ensure_fqdn
def find_hbacrule(module, name):
_args = {
"all": True,
"cn": name,
}
_result = module.ipa_command("hbacrule_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one hbacrule '%s'" % (name))
elif len(_result["result"]) == 1:
res = _result["result"][0]
# hbacsvcgroup names are converted to lower case while creation with
# hbacsvcgroup_add, but builtin names may have mixed case as "Sudo",
# breaking the lower case comparison. Therefore all
# memberservice_hbacsvcgroup items are converted to lower case.
# (See: https://pagure.io/freeipa/issue/9464).
_member = "memberservice_hbacsvcgroup"
if _member in res:
res[_member] = [item.lower() for item in res[_member]]
return res
return None
def gen_args(description, usercategory, hostcategory, servicecategory,
nomembers):
_args = {}
if description is not None:
_args["description"] = description
if usercategory is not None:
_args["usercategory"] = usercategory
if hostcategory is not None:
_args["hostcategory"] = hostcategory
if servicecategory is not None:
_args["servicecategory"] = servicecategory
if nomembers is not None:
_args["nomembers"] = nomembers
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
description=dict(type="str", default=None),
usercategory=dict(type="str", default=None,
aliases=["usercat"], choices=["all", ""]),
hostcategory=dict(type="str", default=None,
aliases=["hostcat"], choices=["all", ""]),
servicecategory=dict(type="str", default=None,
aliases=["servicecat"], choices=["all", ""]),
nomembers=dict(required=False, type='bool', default=None),
host=dict(required=False, type='list', elements="str",
default=None),
hostgroup=dict(required=False, type='list', elements="str",
default=None),
hbacsvc=dict(required=False, type='list', elements="str",
default=None),
hbacsvcgroup=dict(required=False, type='list', elements="str",
default=None),
user=dict(required=False, type='list', elements="str",
default=None),
group=dict(required=False, type='list', elements="str",
default=None),
action=dict(type="str", default="hbacrule",
choices=["member", "hbacrule"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent",
"enabled", "disabled"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
description = ansible_module.params_get("description")
usercategory = ansible_module.params_get("usercategory")
hostcategory = ansible_module.params_get("hostcategory")
servicecategory = ansible_module.params_get("servicecategory")
nomembers = ansible_module.params_get("nomembers")
host = ansible_module.params_get_lowercase("host")
hostgroup = ansible_module.params_get_lowercase("hostgroup")
hbacsvc = ansible_module.params_get_lowercase("hbacsvc")
hbacsvcgroup = ansible_module.params_get_lowercase("hbacsvcgroup")
user = ansible_module.params_get_lowercase("user")
group = ansible_module.params_get_lowercase("group")
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one hbacrule can be added at a time.")
if action == "member":
invalid = ["description", "usercategory", "hostcategory",
"servicecategory", "nomembers"]
else:
if hostcategory == 'all' and any([host, hostgroup]):
ansible_module.fail_json(
msg="Hosts cannot be added when host category='all'")
if usercategory == 'all' and any([user, group]):
ansible_module.fail_json(
msg="Users cannot be added when user category='all'")
if servicecategory == 'all' and any([hbacsvc, hbacsvcgroup]):
ansible_module.fail_json(
msg="Services cannot be added when service category='all'")
elif state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description", "usercategory", "hostcategory",
"servicecategory", "nomembers"]
if action == "hbacrule":
invalid.extend(["host", "hostgroup", "hbacsvc", "hbacsvcgroup",
"user", "group"])
elif state in ["enabled", "disabled"]:
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
if action == "member":
ansible_module.fail_json(
msg="Action member can not be used with states enabled and "
"disabled")
invalid = ["description", "usercategory", "hostcategory",
"servicecategory", "nomembers", "host", "hostgroup",
"hbacsvc", "hbacsvcgroup", "user", "group"]
else:
ansible_module.fail_json(msg="Invalid state '%s'" % state)
ansible_module.params_fail_used_invalid(invalid, state, action)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
# Get default domain
default_domain = ansible_module.ipa_get_domain()
# Ensure fqdn host names, use default domain for simple names
if host is not None:
_host = [ensure_fqdn(x, default_domain).lower() for x in host]
host = _host
commands = []
for name in names:
# Make sure hbacrule exists
res_find = find_hbacrule(ansible_module, name)
host_add, host_del = [], []
hostgroup_add, hostgroup_del = [], []
hbacsvc_add, hbacsvc_del = [], []
hbacsvcgroup_add, hbacsvcgroup_del = [], []
user_add, user_del = [], []
group_add, group_del = [], []
# Create command
if state == "present":
# Generate args
args = gen_args(description, usercategory, hostcategory,
servicecategory, nomembers)
if action == "hbacrule":
# Found the hbacrule
if res_find is not None:
# Remove usercategory, hostcategory and
# servicecategory from args if "" and category
# not in res_find (needed for idempotency)
if "usercategory" in args and \
args["usercategory"] == "" and \
"usercategory" not in res_find:
del args["usercategory"]
if "hostcategory" in args and \
args["hostcategory"] == "" and \
"hostcategory" not in res_find:
del args["hostcategory"]
if "servicecategory" in args and \
args["servicecategory"] == "" and \
"servicecategory" not in res_find:
del args["servicecategory"]
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "hbacrule_mod", args])
else:
commands.append([name, "hbacrule_add", args])
# Set res_find to empty dict for next step
res_find = {}
# Generate addition and removal lists
if host is not None:
host_add, host_del = gen_add_del_lists(
host, res_find.get("memberhost_host"))
if hostgroup is not None:
hostgroup_add, hostgroup_del = gen_add_del_lists(
hostgroup, res_find.get("memberhost_hostgroup"))
if hbacsvc is not None:
hbacsvc_add, hbacsvc_del = gen_add_del_lists(
hbacsvc, res_find.get("memberservice_hbacsvc"),
)
if hbacsvcgroup is not None:
hbacsvcgroup_add, hbacsvcgroup_del = gen_add_del_lists(
hbacsvcgroup,
res_find.get("memberservice_hbacsvcgroup"))
if user is not None:
user_add, user_del = gen_add_del_lists(
user, res_find.get("memberuser_user"))
if group is not None:
group_add, group_del = gen_add_del_lists(
group, res_find.get("memberuser_group"))
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No hbacrule '%s'" % name)
# Generate add lists for host, hostgroup and
# res_find to only try to add hosts and hostgroups
# that not in hbacrule already
if host:
host_add = gen_add_list(
host, res_find.get("memberhost_host"))
if hostgroup:
hostgroup_add = gen_add_list(
hostgroup, res_find.get("memberhost_hostgroup"))
# Generate add lists for hbacsvc, hbacsvcgroup and
# res_find to only try to add hbacsvcs and hbacsvcgroups
# that not in hbacrule already
if hbacsvc:
hbacsvc_add = gen_add_list(
hbacsvc, res_find.get("memberservice_hbacsvc"))
if hbacsvcgroup:
hbacsvcgroup_add = gen_add_list(
hbacsvcgroup,
res_find.get("memberservice_hbacsvcgroup"))
# Generate add lists for user, group and
# res_find to only try to add users and groups
# that not in hbacrule already
if user:
user_add = gen_add_list(
user, res_find.get("memberuser_user"))
if group:
group_add = gen_add_list(
group, res_find.get("memberuser_group"))
elif state == "absent":
if action == "hbacrule":
if res_find is not None:
commands.append([name, "hbacrule_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No hbacrule '%s'" % name)
# Generate intersection lists for host, hostgroup and
# res_find to only try to remove hosts and hostgroups
# that are in hbacrule
if host:
if "memberhost_host" in res_find:
host_del = gen_intersection_list(
host, res_find["memberhost_host"])
if hostgroup:
if "memberhost_hostgroup" in res_find:
hostgroup_del = gen_intersection_list(
hostgroup, res_find["memberhost_hostgroup"])
# Generate intersection lists for hbacsvc, hbacsvcgroup
# and res_find to only try to remove hbacsvcs and
# hbacsvcgroups that are in hbacrule
if hbacsvc:
if "memberservice_hbacsvc" in res_find:
hbacsvc_del = gen_intersection_list(
hbacsvc, res_find["memberservice_hbacsvc"])
if hbacsvcgroup:
if "memberservice_hbacsvcgroup" in res_find:
hbacsvcgroup_del = gen_intersection_list(
hbacsvcgroup,
res_find["memberservice_hbacsvcgroup"])
# Generate intersection lists for user, group and
# res_find to only try to remove users and groups
# that are in hbacrule
if user:
if "memberuser_user" in res_find:
user_del = gen_intersection_list(
user, res_find["memberuser_user"])
if group:
if "memberuser_group" in res_find:
group_del = gen_intersection_list(
group, res_find["memberuser_group"])
elif state == "enabled":
if res_find is None:
ansible_module.fail_json(msg="No hbacrule '%s'" % name)
# hbacrule_enable is not failing on an enabled hbacrule
# Therefore it is needed to have a look at the ipaenabledflag
# in res_find.
# FreeIPA 4.9.10+ and 4.10 use proper mapping for
# boolean values, so we need to convert it to str
# for comparison.
# See: https://github.com/freeipa/freeipa/pull/6294
enabled_flag = str(res_find.get("ipaenabledflag", [False])[0])
if enabled_flag.upper() != "TRUE":
commands.append([name, "hbacrule_enable", {}])
elif state == "disabled":
if res_find is None:
ansible_module.fail_json(msg="No hbacrule '%s'" % name)
# hbacrule_disable is not failing on an enabled hbacrule
# Therefore it is needed to have a look at the ipaenabledflag
# in res_find.
# FreeIPA 4.9.10+ and 4.10 use proper mapping for
# boolean values, so we need to convert it to str
# for comparison.
# See: https://github.com/freeipa/freeipa/pull/6294
enabled_flag = str(res_find.get("ipaenabledflag", [False])[0])
if enabled_flag.upper() != "FALSE":
commands.append([name, "hbacrule_disable", {}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Manage HBAC rule members.
# Add hosts and hostgroups
if len(host_add) > 0 or len(hostgroup_add) > 0:
commands.append([name, "hbacrule_add_host",
{
"host": host_add,
"hostgroup": hostgroup_add,
}])
# Remove hosts and hostgroups
if len(host_del) > 0 or len(hostgroup_del) > 0:
commands.append([name, "hbacrule_remove_host",
{
"host": host_del,
"hostgroup": hostgroup_del,
}])
# Add hbacsvcs and hbacsvcgroups
if len(hbacsvc_add) > 0 or len(hbacsvcgroup_add) > 0:
commands.append([name, "hbacrule_add_service",
{
"hbacsvc": hbacsvc_add,
"hbacsvcgroup": hbacsvcgroup_add,
}])
# Remove hbacsvcs and hbacsvcgroups
if len(hbacsvc_del) > 0 or len(hbacsvcgroup_del) > 0:
commands.append([name, "hbacrule_remove_service",
{
"hbacsvc": hbacsvc_del,
"hbacsvcgroup": hbacsvcgroup_del,
}])
# Add users and groups
if len(user_add) > 0 or len(group_add) > 0:
commands.append([name, "hbacrule_add_user",
{
"user": user_add,
"group": group_add,
}])
# Remove users and groups
if len(user_del) > 0 or len(group_del) > 0:
commands.append([name, "hbacrule_remove_user",
{
"user": user_del,
"group": group_del,
}])
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipahbacsvc.py 0000664 0000000 0000000 00000011635 14600563364 0023220 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipahbacsvc
short_description: Manage FreeIPA HBAC Services
description: Manage FreeIPA HBAC Services
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The group name
type: list
elements: str
required: true
aliases: ["cn", "service"]
description:
description: The HBAC Service description
type: str
required: false
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent"]
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure HBAC Service for http is present
- ipahbacsvc:
ipaadmin_password: SomeADMINpassword
name: http
description: Web service
# Ensure HBAC Service for tftp is absent
- ipahbacsvc:
ipaadmin_password: SomeADMINpassword
name: tftp
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
def find_hbacsvc(module, name):
_args = {
"all": True,
"cn": name,
}
_result = module.ipa_command("hbacsvc_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one hbacsvc '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
return None
def gen_args(description):
_args = {}
if description is not None:
_args["description"] = description
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn", "service"],
required=True),
# present
description=dict(type="str", default=None),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
description = ansible_module.params_get("description")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one hbacsvc can be set at a time.")
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(
msg="No name given.")
invalid = ["description"]
ansible_module.params_fail_used_invalid(invalid, state)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
# Try to find hbacsvc
res_find = find_hbacsvc(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description)
# Found the hbacsvc
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "hbacsvc_mod", args])
else:
commands.append([name, "hbacsvc_add", args])
elif state == "absent":
if res_find is not None:
commands.append([name, "hbacsvc_del", {}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipahbacsvcgroup.py 0000664 0000000 0000000 00000021343 14600563364 0024272 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipahbacsvcgroup
short_description: Manage FreeIPA hbacsvcgroups
description: Manage FreeIPA hbacsvcgroups
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The hbacsvcgroup name
type: list
elements: str
required: true
aliases: ["cn"]
description:
description: The hbacsvcgroup description
type: str
required: false
hbacsvc:
description: List of hbacsvc names assigned to this hbacsvcgroup.
required: false
type: list
elements: str
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
action:
description: Work on hbacsvcgroup or member level
type: str
default: hbacsvcgroup
choices: ["member", "hbacsvcgroup"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent"]
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure hbacsvcgroup login is present
- ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: login
hbacsvc:
- sshd
# Ensure hbacsvc sshd is present in existing login hbacsvcgroup
- ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: databases
hbacsvc:
- sshd
action: member
# Ensure hbacsvc sshd is abdsent in existing login hbacsvcgroup
- ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: databases
hbacsvc:
- sshd
action: member
state: absent
# Ensure hbacsvcgroup login is absent
- ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: login
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
gen_intersection_list
def find_hbacsvcgroup(module, name):
_args = {
"all": True,
"cn": name,
}
_result = module.ipa_command("hbacsvcgroup_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one hbacsvcgroup '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
return None
def gen_args(description, nomembers):
_args = {}
if description is not None:
_args["description"] = description
if nomembers is not None:
_args["nomembers"] = nomembers
return _args
def gen_member_args(hbacsvc):
_args = {}
if hbacsvc is not None:
_args["member_hbacsvc"] = hbacsvc
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
description=dict(type="str", default=None),
nomembers=dict(required=False, type='bool', default=None),
hbacsvc=dict(required=False, type='list', elements="str",
default=None),
action=dict(type="str", default="hbacsvcgroup",
choices=["member", "hbacsvcgroup"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
description = ansible_module.params_get("description")
nomembers = ansible_module.params_get("nomembers")
hbacsvc = ansible_module.params_get_lowercase("hbacsvc")
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one hbacsvcgroup can be added at a time.")
if action == "member":
invalid = ["description", "nomembers"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(
msg="No name given.")
invalid = ["description", "nomembers"]
if action == "hbacsvcgroup":
invalid.extend(["hbacsvc"])
ansible_module.params_fail_used_invalid(invalid, state, action)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
# Make sure hbacsvcgroup exists
res_find = find_hbacsvcgroup(ansible_module, name)
hbacsvc_add, hbacsvc_del = [], []
# Create command
if state == "present":
# Generate args
args = gen_args(description, nomembers)
if action == "hbacsvcgroup":
# Found the hbacsvcgroup
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "hbacsvcgroup_mod", args])
else:
commands.append([name, "hbacsvcgroup_add", args])
# Set res_find to empty dict for next step
res_find = {}
member_args = gen_member_args(hbacsvc)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
if hbacsvc is not None:
hbacsvc_add, hbacsvc_del = gen_add_del_lists(
hbacsvc, res_find.get("member_hbacsvc"))
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No hbacsvcgroup '%s'" % name)
# Ensure members are present
if hbacsvc:
hbacsvc_add = gen_add_list(
hbacsvc, res_find.get("member_hbacsvc"))
elif state == "absent":
if action == "hbacsvcgroup":
if res_find is not None:
commands.append([name, "hbacsvcgroup_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No hbacsvcgroup '%s'" % name)
# Ensure members are absent
if hbacsvc:
hbacsvc_del = gen_intersection_list(
hbacsvc, res_find.get("member_hbacsvc"))
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Manage members
if len(hbacsvc_add) > 0:
commands.append([name, "hbacsvcgroup_add_member",
{
"hbacsvc": hbacsvc_add
}])
# Remove members
if len(hbacsvc_del) > 0:
commands.append([name,
"hbacsvcgroup_remove_member",
{
"hbacsvc": hbacsvc_del
}])
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipahost.py 0000664 0000000 0000000 00000170420 14600563364 0022562 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipahost
short_description: Manage FreeIPA hosts
description: Manage FreeIPA hosts
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The full qualified domain name.
type: list
elements: str
aliases: ["fqdn"]
required: false
hosts:
description: The list of host dicts
required: false
type: list
elements: dict
suboptions:
name:
description: The host (internally uid).
type: str
aliases: ["fqdn"]
required: true
description:
description: The host description
type: str
required: false
locality:
description: Host locality (e.g. "Baltimore, MD")
type: str
required: false
location:
description: Host physical location hist (e.g. "Lab 2")
type: str
aliases: ["ns_host_location"]
required: false
platform:
description: Host hardware platform (e.g. "Lenovo T61")
type: str
aliases: ["ns_hardware_platform"]
required: false
os:
description: Host operating system and version (e.g. "Fedora 9")
type: str
aliases: ["ns_os_version"]
required: false
password:
description: Password used in bulk enrollment
type: str
aliases: ["user_password", "userpassword"]
required: false
random:
description:
Initiate the generation of a random password to be used in bulk
enrollment
type: bool
aliases: ["random_password"]
required: false
certificate:
description: List of base-64 encoded host certificates
type: list
elements: str
aliases: ["usercertificate"]
required: false
managedby_host:
description: List of hosts that can manage this host
type: list
elements: str
required: false
principal:
description: List of principal aliases for this host
type: list
elements: str
aliases: ["principalname", "krbprincipalname"]
required: false
allow_create_keytab_user:
description: Users allowed to create a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_user"]
required: false
allow_create_keytab_group:
description: Groups allowed to create a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_group"]
required: false
allow_create_keytab_host:
description: Hosts allowed to create a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_host"]
required: false
allow_create_keytab_hostgroup:
description: Hostgroups allowed to create a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_hostgroup"]
required: false
allow_retrieve_keytab_user:
description: Users allowed to retrieve a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_user"]
required: false
allow_retrieve_keytab_group:
description: Groups allowed to retrieve a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_group"]
required: false
allow_retrieve_keytab_host:
description: Hosts allowed to retrieve a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_host"]
required: false
allow_retrieve_keytab_hostgroup:
description: Hostgroups allowed to retrieve a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_hostgroup"]
required: false
mac_address:
description: List of hardware MAC addresses.
type: list
elements: str
aliases: ["macaddress"]
required: false
sshpubkey:
description: List of SSH public keys
type: list
elements: str
aliases: ["ipasshpubkey"]
required: false
userclass:
description:
Host category (semantics placed on this attribute are for local
interpretation)
type: list
elements: str
aliases: ["class"]
required: false
auth_ind:
description:
Defines an allow list for Authentication Indicators. Use 'otp'
to allow OTP-based 2FA authentications. Use 'radius' to allow
RADIUS-based 2FA authentications. Other values may be used
for custom configurations. Use empty string to reset auth_ind
to the initial value.
type: list
elements: str
aliases: ["krbprincipalauthind"]
choices: ["radius", "otp", "pkinit", "hardened", "idp", ""]
required: false
requires_pre_auth:
description: Pre-authentication is required for the service
type: bool
aliases: ["ipakrbrequirespreauth"]
required: false
ok_as_delegate:
description: Client credentials may be delegated to the service
type: bool
aliases: ["ipakrbokasdelegate"]
required: false
ok_to_auth_as_delegate:
description:
The service is allowed to authenticate on behalf of a client
type: bool
aliases: ["ipakrboktoauthasdelegate"]
required: false
force:
description: Force host name even if not in DNS
type: bool
required: false
reverse:
description: Reverse DNS detection
type: bool
required: false
ip_address:
description:
The host IP address list (IPv4 and IPv6). No IP address conflict
check will be done.
type: list
elements: str
aliases: ["ipaddress"]
required: false
update_dns:
description:
Controls the update of the DNS SSHFP records for existing hosts and
the removal of all DNS entries if a host gets removed with state
absent.
type: bool
aliases: ["updatedns"]
required: false
description:
description: The host description
type: str
required: false
locality:
description: Host locality (e.g. "Baltimore, MD")
type: str
required: false
location:
description: Host location (e.g. "Lab 2")
type: str
aliases: ["ns_host_location"]
required: false
platform:
description: Host hardware platform (e.g. "Lenovo T61")
type: str
aliases: ["ns_hardware_platform"]
required: false
os:
description: Host operating system and version (e.g. "Fedora 9")
type: str
aliases: ["ns_os_version"]
required: false
password:
description: Password used in bulk enrollment
type: str
aliases: ["user_password", "userpassword"]
required: false
random:
description:
Initiate the generation of a random password to be used in bulk
enrollment
type: bool
aliases: ["random_password"]
required: false
certificate:
description: List of base-64 encoded host certificates
type: list
elements: str
aliases: ["usercertificate"]
required: false
managedby_host:
description: List of hosts that can manage this host
type: list
elements: str
required: false
principal:
description: List of principal aliases for this host
type: list
elements: str
aliases: ["principalname", "krbprincipalname"]
required: false
allow_create_keytab_user:
description: Users allowed to create a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_user"]
required: false
allow_create_keytab_group:
description: Groups allowed to create a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_group"]
required: false
allow_create_keytab_host:
description: Hosts allowed to create a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_host"]
required: false
allow_create_keytab_hostgroup:
description: Hostgroups allowed to create a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_hostgroup"]
required: false
allow_retrieve_keytab_user:
description: Users allowed to retrieve a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_user"]
required: false
allow_retrieve_keytab_group:
description: Groups allowed to retrieve a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_group"]
required: false
allow_retrieve_keytab_host:
description: Hosts allowed to retrieve a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_host"]
required: false
allow_retrieve_keytab_hostgroup:
description: Hostgroups allowed to retrieve a keytab of this host
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_hostgroup"]
required: false
mac_address:
description: List of hardware MAC addresses.
type: list
elements: str
aliases: ["macaddress"]
required: false
sshpubkey:
description: List of SSH public keys
type: list
elements: str
aliases: ["ipasshpubkey"]
required: false
userclass:
description:
Host category (semantics placed on this attribute are for local
interpretation)
type: list
elements: str
aliases: ["class"]
required: false
auth_ind:
description:
Defines an allow list for Authentication Indicators. Use 'otp'
to allow OTP-based 2FA authentications. Use 'radius' to allow
RADIUS-based 2FA authentications. Other values may be used
for custom configurations. Use empty string to reset auth_ind
to the initial value.
type: list
elements: str
aliases: ["krbprincipalauthind"]
choices: ["radius", "otp", "pkinit", "hardened", "idp", ""]
required: false
requires_pre_auth:
description: Pre-authentication is required for the service
type: bool
aliases: ["ipakrbrequirespreauth"]
required: false
ok_as_delegate:
description: Client credentials may be delegated to the service
type: bool
aliases: ["ipakrbokasdelegate"]
required: false
ok_to_auth_as_delegate:
description:
The service is allowed to authenticate on behalf of a client
type: bool
aliases: ["ipakrboktoauthasdelegate"]
required: false
force:
description: Force host name even if not in DNS
type: bool
required: false
reverse:
description: Reverse DNS detection
type: bool
required: false
ip_address:
description:
The host IP address list (IPv4 and IPv6). No IP address conflict
check will be done.
type: list
elements: str
aliases: ["ipaddress"]
required: false
update_dns:
description:
Controls the update of the DNS SSHFP records for existing hosts and
the removal of all DNS entries if a host gets removed with state
absent.
type: bool
aliases: ["updatedns"]
required: false
update_password:
description:
Set password for a host in present state only on creation or always
type: str
choices: ["always", "on_create"]
action:
description: Work on host or member level
type: str
default: "host"
choices: ["member", "host"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent",
"disabled"]
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure host is present
- ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
description: Example host
ip_address: 192.168.0.123
locality: Lab
ns_host_location: Lab
ns_os_version: CentOS 7
ns_hardware_platform: Lenovo T61
mac_address:
- "08:00:27:E3:B1:2D"
- "52:54:00:BD:97:1E"
state: present
# Ensure host is present without DNS
- ipahost:
ipaadmin_password: SomeADMINpassword
name: host02.example.com
description: Example host
force: yes
# Ensure multiple hosts are present with random passwords
- ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
random: yes
- name: host02.example.com
random: yes
# Initiate generation of a random password for the host
- ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
description: Example host
ip_address: 192.168.0.123
random: yes
# Ensure multiple hosts are present with principals
- ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.example.com
principal:
- host/testhost01.example.com
- name: host02.example.com
principal:
- host/myhost01.example.com
action: member
# Ensure host is disabled
- ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
update_dns: yes
state: disabled
# Ensure host is absent
- ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.example.com
state: absent
"""
RETURN = """
host:
description: Host dict with random password
returned: If random is yes and host did not exist or update_password is yes
type: dict
contains:
randompassword:
description: The generated random password
type: str
returned: |
If only one host is handled by the module without using hosts parameter
name:
description: The host name of the host that got a new random password
returned: |
If several hosts are handled by the module with the hosts parameter
type: dict
contains:
randompassword:
description: The generated random password
type: str
returned: always
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, \
encode_certificate, is_ipv4_addr, is_ipv6_addr, ipalib_errors
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_host(module, name):
_args = {
"all": True,
}
try:
_result = module.ipa_command("host_show", name, _args)
except ipalib_errors.NotFound as e:
msg = str(e)
if "host not found" in msg:
return None
module.fail_json(msg="host_show failed: %s" % msg)
_res = _result["result"]
certs = _res.get("usercertificate")
if certs is not None:
_res["usercertificate"] = [encode_certificate(cert) for
cert in certs]
return _res
def find_dnsrecord(module, name):
"""
Search for a DNS record.
This function may raise ipalib_errors.NotFound in some cases,
and it should be handled by the caller.
"""
domain_name = name[name.find(".") + 1:]
host_name = name[:name.find(".")]
_args = {
"all": True,
"idnsname": host_name
}
_result = module.ipa_command("dnsrecord_show", domain_name, _args)
return _result["result"]
def show_host(module, name):
_result = module.ipa_command("host_show", name, {})
return _result["result"]
def gen_args(description, locality, location, platform, os, password, random,
mac_address, sshpubkey, userclass, auth_ind, requires_pre_auth,
ok_as_delegate, ok_to_auth_as_delegate, force, _reverse,
ip_address, update_dns):
# certificate, managedby_host, principal, create_keytab_* and
# allow_retrieve_keytab_* are not handled here
_args = {}
if description is not None:
_args["description"] = description
if locality is not None:
_args["l"] = locality
if location is not None:
_args["nshostlocation"] = location
if platform is not None:
_args["nshardwareplatform"] = platform
if os is not None:
_args["nsosversion"] = os
if password is not None:
_args["userpassword"] = password
if random is not None:
_args["random"] = random
if mac_address is not None:
_args["macaddress"] = mac_address
if sshpubkey is not None:
_args["ipasshpubkey"] = sshpubkey
if userclass is not None:
_args["userclass"] = userclass
if auth_ind is not None:
_args["krbprincipalauthind"] = auth_ind
if requires_pre_auth is not None:
_args["ipakrbrequirespreauth"] = requires_pre_auth
if ok_as_delegate is not None:
_args["ipakrbokasdelegate"] = ok_as_delegate
if ok_to_auth_as_delegate is not None:
_args["ipakrboktoauthasdelegate"] = ok_to_auth_as_delegate
if force is not None:
_args["force"] = force
if ip_address is not None:
# IP addresses are handed extra, therefore it is needed to set
# the force option here to make sure that host-add is able to
# add a host without IP address.
_args["force"] = True
if update_dns is not None:
_args["updatedns"] = update_dns
return _args
def gen_dnsrecord_args(module, ip_address, reverse):
_args = {}
if reverse is not None:
_args["a_extra_create_reverse"] = reverse
_args["aaaa_extra_create_reverse"] = reverse
if ip_address is not None:
for ip in ip_address:
if is_ipv4_addr(ip):
_args.setdefault("arecord", []).append(ip)
elif is_ipv6_addr(ip):
_args.setdefault("aaaarecord", []).append(ip)
else:
module.fail_json(msg="'%s' is not a valid IP address." % ip)
return _args
def check_parameters( # pylint: disable=unused-argument
module, state, action,
description, locality, location, platform, os, password, random,
certificate, managedby_host, principal, allow_create_keytab_user,
allow_create_keytab_group, allow_create_keytab_host,
allow_create_keytab_hostgroup, allow_retrieve_keytab_user,
allow_retrieve_keytab_group, allow_retrieve_keytab_host,
allow_retrieve_keytab_hostgroup, mac_address, sshpubkey,
userclass, auth_ind, requires_pre_auth, ok_as_delegate,
ok_to_auth_as_delegate, force, reverse, ip_address, update_dns,
update_password):
invalid = []
if state == "present":
if action == "member":
# certificate, managedby_host, principal,
# allow_create_keytab_*, allow_retrieve_keytab_*,
invalid = ["description", "locality", "location", "platform",
"os", "password", "random", "mac_address", "sshpubkey",
"userclass", "auth_ind", "requires_pre_auth",
"ok_as_delegate", "ok_to_auth_as_delegate", "force",
"reverse", "update_dns", "update_password"]
if state == "absent":
invalid = ["description", "locality", "location", "platform", "os",
"password", "random", "mac_address", "sshpubkey",
"userclass", "auth_ind", "requires_pre_auth",
"ok_as_delegate", "ok_to_auth_as_delegate", "force",
"reverse", "update_password"]
if action == "host":
invalid = [
"certificate", "managedby_host", "principal",
"allow_create_keytab_user", "allow_create_keytab_group",
"allow_create_keytab_host", "allow_create_keytab_hostgroup",
"allow_retrieve_keytab_user", "allow_retrieve_keytab_group",
"allow_retrieve_keytab_host",
"allow_retrieve_keytab_hostgroup"
]
module.params_fail_used_invalid(invalid, state, action)
def check_authind(module, auth_ind):
_invalid = module.ipa_command_invalid_param_choices(
"host_add", "krbprincipalauthind", auth_ind)
if _invalid:
module.fail_json(
msg="The use of krbprincipalauthind '%s' is not supported "
"by your IPA version" % "','".join(_invalid))
# pylint: disable=unused-argument
def result_handler(module, result, command, name, args, errors, exit_args,
single_host):
if "random" in args and command in ["host_add", "host_mod"] \
and "randompassword" in result["result"]:
if single_host:
exit_args["randompassword"] = \
result["result"]["randompassword"]
else:
exit_args.setdefault(name, {})["randompassword"] = \
result["result"]["randompassword"]
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
# pylint: disable=unused-argument
def exception_handler(module, ex, errors, exit_args, single_host):
msg = str(ex)
if "already contains" in msg \
or "does not contain" in msg:
return True
# The canonical principal name may not be removed
if "equal to the canonical principal name must" in msg:
return True
# Host is already disabled, ignore error
if "This entry is already disabled" in msg:
return True
# Ignore no modification error.
if "no modifications to be performed" in msg:
return True
return False
def main():
host_spec = dict(
# present
description=dict(type="str", default=None),
locality=dict(type="str", default=None),
location=dict(type="str", aliases=["ns_host_location"],
default=None),
platform=dict(type="str", aliases=["ns_hardware_platform"],
default=None),
os=dict(type="str", aliases=["ns_os_version"], default=None),
password=dict(type="str",
aliases=["user_password", "userpassword"],
default=None, no_log=True),
random=dict(type="bool", aliases=["random_password"],
default=None),
certificate=dict(type="list", elements="str",
aliases=["usercertificate"], default=None),
managedby_host=dict(type="list", elements="str", default=None),
principal=dict(type="list", elements="str",
aliases=["principalname", "krbprincipalname"],
default=None),
allow_create_keytab_user=dict(
type="list", elements="str",
aliases=["ipaallowedtoperform_write_keys_user"],
default=None, no_log=False),
allow_create_keytab_group=dict(
type="list", elements="str",
aliases=["ipaallowedtoperform_write_keys_group"],
default=None, no_log=False),
allow_create_keytab_host=dict(
type="list", elements="str",
aliases=["ipaallowedtoperform_write_keys_host"],
default=None, no_log=False),
allow_create_keytab_hostgroup=dict(
type="list", elements="str",
aliases=["ipaallowedtoperform_write_keys_hostgroup"],
default=None, no_log=False),
allow_retrieve_keytab_user=dict(
type="list", elements="str",
aliases=["ipaallowedtoperform_read_keys_user"],
default=None, no_log=False),
allow_retrieve_keytab_group=dict(
type="list", elements="str",
aliases=["ipaallowedtoperform_read_keys_group"],
default=None, no_log=False),
allow_retrieve_keytab_host=dict(
type="list", elements="str",
aliases=["ipaallowedtoperform_read_keys_host"],
default=None, no_log=False),
allow_retrieve_keytab_hostgroup=dict(
type="list", elements="str",
aliases=["ipaallowedtoperform_read_keys_hostgroup"],
default=None, no_log=False),
mac_address=dict(type="list", elements="str", aliases=["macaddress"],
default=None),
sshpubkey=dict(type="list", elements="str", aliases=["ipasshpubkey"],
default=None),
userclass=dict(type="list", elements="str", aliases=["class"],
default=None),
auth_ind=dict(type='list', elements="str",
aliases=["krbprincipalauthind"], default=None,
choices=["radius", "otp", "pkinit", "hardened", "idp",
""]),
requires_pre_auth=dict(type="bool", aliases=["ipakrbrequirespreauth"],
default=None),
ok_as_delegate=dict(type="bool", aliases=["ipakrbokasdelegate"],
default=None),
ok_to_auth_as_delegate=dict(type="bool",
aliases=["ipakrboktoauthasdelegate"],
default=None),
force=dict(type='bool', default=None),
reverse=dict(type='bool', default=None),
ip_address=dict(type="list", elements="str", aliases=["ipaddress"],
default=None),
update_dns=dict(type="bool", aliases=["updatedns"],
default=None),
# no_members
# for update:
# krbprincipalname
)
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["fqdn"],
default=None, required=False),
hosts=dict(type="list", default=None,
options=dict(
# Here name is a simple string
name=dict(type="str", aliases=["fqdn"],
required=True),
# Add host specific parameters
**host_spec
),
elements='dict', required=False),
# mod
update_password=dict(type='str', default=None, no_log=False,
choices=['always', 'on_create']),
# general
action=dict(type="str", default="host",
choices=["member", "host"]),
state=dict(type="str", default="present",
choices=["present", "absent", "disabled"]),
# Add host specific parameters for simple use case
**host_spec
),
mutually_exclusive=[["name", "hosts"]],
required_one_of=[["name", "hosts"]],
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
hosts = ansible_module.params_get("hosts")
# present
description = ansible_module.params_get("description")
locality = ansible_module.params_get("locality")
location = ansible_module.params_get("location")
platform = ansible_module.params_get("platform")
os = ansible_module.params_get("os")
password = ansible_module.params_get("password")
random = ansible_module.params_get("random")
certificate = ansible_module.params_get("certificate")
managedby_host = ansible_module.params_get("managedby_host")
principal = ansible_module.params_get("principal")
allow_create_keytab_user = ansible_module.params_get(
"allow_create_keytab_user")
allow_create_keytab_group = ansible_module.params_get(
"allow_create_keytab_group")
allow_create_keytab_host = ansible_module.params_get(
"allow_create_keytab_host")
allow_create_keytab_hostgroup = ansible_module.params_get(
"allow_create_keytab_hostgroup")
allow_retrieve_keytab_user = ansible_module.params_get(
"allow_retrieve_keytab_user")
allow_retrieve_keytab_group = ansible_module.params_get(
"allow_retrieve_keytab_group")
allow_retrieve_keytab_host = ansible_module.params_get(
"allow_retrieve_keytab_host")
allow_retrieve_keytab_hostgroup = ansible_module.params_get(
"allow_retrieve_keytab_hostgroup")
mac_address = ansible_module.params_get("mac_address")
sshpubkey = ansible_module.params_get(
"sshpubkey", allow_empty_list_item=True)
userclass = ansible_module.params_get("userclass")
auth_ind = ansible_module.params_get(
"auth_ind", allow_empty_list_item=True)
requires_pre_auth = ansible_module.params_get("requires_pre_auth")
ok_as_delegate = ansible_module.params_get("ok_as_delegate")
ok_to_auth_as_delegate = ansible_module.params_get(
"ok_to_auth_as_delegate")
force = ansible_module.params_get("force")
reverse = ansible_module.params_get("reverse")
ip_address = ansible_module.params_get("ip_address")
update_dns = ansible_module.params_get("update_dns")
update_password = ansible_module.params_get("update_password")
# general
action = ansible_module.params_get("action")
state = ansible_module.params_get("state")
# Check parameters
if (names is None or len(names) < 1) and \
(hosts is None or len(hosts) < 1):
ansible_module.fail_json(msg="One of name and hosts is required")
if state == "present":
if names is not None and len(names) != 1:
ansible_module.fail_json(
msg="Only one host can be added at a time.")
check_parameters(
ansible_module, state, action,
description, locality, location, platform, os, password, random,
certificate, managedby_host, principal, allow_create_keytab_user,
allow_create_keytab_group, allow_create_keytab_host,
allow_create_keytab_hostgroup, allow_retrieve_keytab_user,
allow_retrieve_keytab_group, allow_retrieve_keytab_host,
allow_retrieve_keytab_hostgroup, mac_address, sshpubkey, userclass,
auth_ind, requires_pre_auth, ok_as_delegate, ok_to_auth_as_delegate,
force, reverse, ip_address, update_dns, update_password)
# Use hosts if names is None
if hosts is not None:
names = hosts
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
# Check version specific settings
check_authind(ansible_module, auth_ind)
server_realm = ansible_module.ipa_get_realm()
commands = []
host_set = set()
for host in names:
if isinstance(host, dict):
name = host.get("name")
if name in host_set:
ansible_module.fail_json(
msg="host '%s' is used more than once" % name)
host_set.add(name)
description = host.get("description")
locality = host.get("locality")
location = host.get("location")
platform = host.get("platform")
os = host.get("os")
password = host.get("password")
random = host.get("random")
certificate = host.get("certificate")
managedby_host = host.get("managedby_host")
principal = host.get("principal")
allow_create_keytab_user = host.get(
"allow_create_keytab_user")
allow_create_keytab_group = host.get(
"allow_create_keytab_group")
allow_create_keytab_host = host.get(
"allow_create_keytab_host")
allow_create_keytab_hostgroup = host.get(
"allow_create_keytab_hostgroup")
allow_retrieve_keytab_user = host.get(
"allow_retrieve_keytab_user")
allow_retrieve_keytab_group = host.get(
"allow_retrieve_keytab_group")
allow_retrieve_keytab_host = host.get(
"allow_retrieve_keytab_host")
allow_retrieve_keytab_hostgroup = host.get(
"allow_retrieve_keytab_hostgroup")
mac_address = host.get("mac_address")
sshpubkey = host.get("sshpubkey")
userclass = host.get("userclass")
auth_ind = host.get("auth_ind")
check_authind(ansible_module, auth_ind)
requires_pre_auth = host.get("requires_pre_auth")
ok_as_delegate = host.get("ok_as_delegate")
ok_to_auth_as_delegate = host.get("ok_to_auth_as_delegate")
force = host.get("force")
reverse = host.get("reverse")
ip_address = host.get("ip_address")
update_dns = host.get("update_dns")
# update_password is not part of hosts structure
# action is not part of hosts structure
# state is not part of hosts structure
check_parameters(
ansible_module, state, action,
description, locality, location, platform, os, password,
random, certificate, managedby_host, principal,
allow_create_keytab_user, allow_create_keytab_group,
allow_create_keytab_host, allow_create_keytab_hostgroup,
allow_retrieve_keytab_user, allow_retrieve_keytab_group,
allow_retrieve_keytab_host,
allow_retrieve_keytab_hostgroup, mac_address, sshpubkey,
userclass, auth_ind, requires_pre_auth, ok_as_delegate,
ok_to_auth_as_delegate, force, reverse, ip_address,
update_dns, update_password)
elif isinstance(host, (str, unicode)):
name = host
else:
ansible_module.fail_json(msg="Host '%s' is not valid" %
repr(host))
# Make sure host exists
res_find = find_host(ansible_module, name)
try:
res_find_dnsrecord = find_dnsrecord(ansible_module, name)
except ipalib_errors.NotFound as e:
msg = str(e)
dns_not_configured = "DNS is not configured" in msg
dns_zone_not_found = "DNS zone not found" in msg
dns_res_not_found = "DNS resource record not found" in msg
if (
dns_res_not_found
or ip_address is None
and (dns_not_configured or dns_zone_not_found)
):
# IP address(es) not given and no DNS support in IPA
# -> Ignore failure
# IP address(es) not given and DNS zone is not found
# -> Ignore failure
res_find_dnsrecord = None
else:
ansible_module.fail_json(msg="%s: %s" % (host, msg))
# Create command
if state == "present":
# Generate args
args = gen_args(
description, locality, location, platform, os, password,
random, mac_address, sshpubkey, userclass, auth_ind,
requires_pre_auth, ok_as_delegate, ok_to_auth_as_delegate,
force, reverse, ip_address, update_dns)
dnsrecord_args = gen_dnsrecord_args(
ansible_module, ip_address, reverse)
if action == "host":
# Found the host
if res_find is not None:
# Ignore password with update_password == on_create
if update_password == "on_create":
# Ignore userpassword and random for existing
# host if update_password is "on_create"
if "userpassword" in args:
del args["userpassword"]
if "random" in args:
del args["random"]
elif "userpassword" in args or "random" in args:
# Allow an existing OTP to be reset but don't
# allow a OTP or to be added to an enrolled host.
# Also do not allow to change the password for an
# enrolled host.
if not res_find["has_password"] and \
res_find["has_keytab"]:
ansible_module.fail_json(
msg="%s: Password cannot be set on "
"enrolled host." % host
)
# Ignore force, ip_address and no_reverse for mod
for x in ["force", "ip_address", "no_reverse"]:
if x in args:
del args[x]
# Ignore auth_ind if it is empty (for resetting)
# and not set in for the host
if "krbprincipalauthind" not in res_find and \
"krbprincipalauthind" in args and \
args["krbprincipalauthind"] == ['']:
del args["krbprincipalauthind"]
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "host_mod", args])
elif random and "userpassword" in res_find:
# Host exists and random is set, return
# userpassword
if len(names) == 1:
exit_args["userpassword"] = \
res_find["userpassword"]
else:
exit_args.setdefault("hosts", {})[name] = {
"userpassword": res_find["userpassword"]
}
else:
# Remove update_dns as it is not supported by host_add
if "updatedns" in args:
del args["updatedns"]
commands.append([name, "host_add", args])
# Handle members: certificate, managedby_host, principal,
# allow_create_keytab and allow_retrieve_keytab
if res_find is not None:
certificate_add, certificate_del = gen_add_del_lists(
certificate, res_find.get("usercertificate"))
managedby_host_add, managedby_host_del = \
gen_add_del_lists(managedby_host,
res_find.get("managedby_host"))
principal_add, principal_del = gen_add_del_lists(
principal, res_find.get("principal"))
# Principals are not returned as utf8 for IPA using
# python2 using host_show, therefore we need to
# convert the principals that we should remove.
principal_del = [unicode(x) for x in principal_del]
(allow_create_keytab_user_add,
allow_create_keytab_user_del) = \
gen_add_del_lists(
allow_create_keytab_user,
res_find.get(
"ipaallowedtoperform_write_keys_user"))
(allow_create_keytab_group_add,
allow_create_keytab_group_del) = \
gen_add_del_lists(
allow_create_keytab_group,
res_find.get(
"ipaallowedtoperform_write_keys_group"))
(allow_create_keytab_host_add,
allow_create_keytab_host_del) = \
gen_add_del_lists(
allow_create_keytab_host,
res_find.get(
"ipaallowedtoperform_write_keys_host"))
(allow_create_keytab_hostgroup_add,
allow_create_keytab_hostgroup_del) = \
gen_add_del_lists(
allow_create_keytab_hostgroup,
res_find.get(
"ipaallowedtoperform_write_keys_"
"hostgroup"))
(allow_retrieve_keytab_user_add,
allow_retrieve_keytab_user_del) = \
gen_add_del_lists(
allow_retrieve_keytab_user,
res_find.get(
"ipaallowedtoperform_read_keys_user"))
(allow_retrieve_keytab_group_add,
allow_retrieve_keytab_group_del) = \
gen_add_del_lists(
allow_retrieve_keytab_group,
res_find.get(
"ipaallowedtoperform_read_keys_group"))
(allow_retrieve_keytab_host_add,
allow_retrieve_keytab_host_del) = \
gen_add_del_lists(
allow_retrieve_keytab_host,
res_find.get(
"ipaallowedtoperform_read_keys_host"))
(allow_retrieve_keytab_hostgroup_add,
allow_retrieve_keytab_hostgroup_del) = \
gen_add_del_lists(
allow_retrieve_keytab_hostgroup,
res_find.get(
"ipaallowedtoperform_read_keys_hostgroup"))
# IP addresses are not really a member of hosts, but
# we will simply treat it as this to enable the
# addition and removal of IPv4 and IPv6 addresses in
# a simple way.
_dnsrec = res_find_dnsrecord or {}
dnsrecord_a_add, dnsrecord_a_del = gen_add_del_lists(
dnsrecord_args.get("arecord"),
_dnsrec.get("arecord"))
dnsrecord_aaaa_add, dnsrecord_aaaa_del = \
gen_add_del_lists(
dnsrecord_args.get("aaaarecord"),
_dnsrec.get("aaaarecord"))
else:
if res_find is None:
ansible_module.fail_json(
msg="No host '%s'" % name)
if action != "host" or (action == "host" and res_find is None):
certificate_add = certificate or []
certificate_del = []
managedby_host_add = managedby_host or []
managedby_host_del = []
principal_add = principal or []
principal_del = []
allow_create_keytab_user_add = \
allow_create_keytab_user or []
allow_create_keytab_user_del = []
allow_create_keytab_group_add = \
allow_create_keytab_group or []
allow_create_keytab_group_del = []
allow_create_keytab_host_add = \
allow_create_keytab_host or []
allow_create_keytab_host_del = []
allow_create_keytab_hostgroup_add = \
allow_create_keytab_hostgroup or []
allow_create_keytab_hostgroup_del = []
allow_retrieve_keytab_user_add = \
allow_retrieve_keytab_user or []
allow_retrieve_keytab_user_del = []
allow_retrieve_keytab_group_add = \
allow_retrieve_keytab_group or []
allow_retrieve_keytab_group_del = []
allow_retrieve_keytab_host_add = \
allow_retrieve_keytab_host or []
allow_retrieve_keytab_host_del = []
allow_retrieve_keytab_hostgroup_add = \
allow_retrieve_keytab_hostgroup or []
allow_retrieve_keytab_hostgroup_del = []
dnsrecord_a_add = dnsrecord_args.get("arecord") or []
dnsrecord_a_del = []
dnsrecord_aaaa_add = dnsrecord_args.get("aaaarecord") or []
dnsrecord_aaaa_del = []
# Remove canonical principal from principal_del
canonical_principal = "host/" + name + "@" + server_realm
if canonical_principal in principal_del and \
action == "host" and (principal is not None or
canonical_principal not in principal):
principal_del.remove(canonical_principal)
# Remove canonical managedby managedby_host_del for
# action host if managedby_host is set and the canonical
# managedby host is not in the managedby_host list.
canonical_managedby_host = name
if canonical_managedby_host in managedby_host_del and \
action == "host" and (managedby_host is None or
canonical_managedby_host not in
managedby_host):
managedby_host_del.remove(canonical_managedby_host)
# Certificates need to be added and removed one by one,
# because if entry already exists, the processing of
# the remaining enries is stopped. The same applies to
# the removal of non-existing entries.
# Add certificates
for _certificate in certificate_add:
commands.append([name, "host_add_cert",
{
"usercertificate":
_certificate,
}])
# Remove certificates
for _certificate in certificate_del:
commands.append([name, "host_remove_cert",
{
"usercertificate":
_certificate,
}])
# Managedby_Hosts need to be added and removed one by one,
# because if entry already exists, the processing of
# the remaining enries is stopped. The same applies to
# the removal of non-existing entries.
# Add managedby_hosts
for _managedby_host in managedby_host_add:
commands.append([name, "host_add_managedby",
{
"host":
_managedby_host,
}])
# Remove managedby_hosts
for _managedby_host in managedby_host_del:
commands.append([name, "host_remove_managedby",
{
"host":
_managedby_host,
}])
# Principals need to be added and removed one by one,
# because if entry already exists, the processing of
# the remaining enries is stopped. The same applies to
# the removal of non-existing entries.
# Add principals
for _principal in principal_add:
commands.append([name, "host_add_principal",
{
"krbprincipalname":
_principal,
}])
# Remove principals
for _principal in principal_del:
commands.append([name, "host_remove_principal",
{
"krbprincipalname":
_principal,
}])
# Allow create keytab
if len(allow_create_keytab_user_add) > 0 or \
len(allow_create_keytab_group_add) > 0 or \
len(allow_create_keytab_host_add) > 0 or \
len(allow_create_keytab_hostgroup_add) > 0:
commands.append(
[name, "host_allow_create_keytab",
{
"user": allow_create_keytab_user_add,
"group": allow_create_keytab_group_add,
"host": allow_create_keytab_host_add,
"hostgroup": allow_create_keytab_hostgroup_add,
}])
# Disallow create keytab
if len(allow_create_keytab_user_del) > 0 or \
len(allow_create_keytab_group_del) > 0 or \
len(allow_create_keytab_host_del) > 0 or \
len(allow_create_keytab_hostgroup_del) > 0:
commands.append(
[name, "host_disallow_create_keytab",
{
"user": allow_create_keytab_user_del,
"group": allow_create_keytab_group_del,
"host": allow_create_keytab_host_del,
"hostgroup": allow_create_keytab_hostgroup_del,
}])
# Allow retrieve keytab
if len(allow_retrieve_keytab_user_add) > 0 or \
len(allow_retrieve_keytab_group_add) > 0 or \
len(allow_retrieve_keytab_host_add) > 0 or \
len(allow_retrieve_keytab_hostgroup_add) > 0:
commands.append(
[name, "host_allow_retrieve_keytab",
{
"user": allow_retrieve_keytab_user_add,
"group": allow_retrieve_keytab_group_add,
"host": allow_retrieve_keytab_host_add,
"hostgroup": allow_retrieve_keytab_hostgroup_add,
}])
# Disallow retrieve keytab
if len(allow_retrieve_keytab_user_del) > 0 or \
len(allow_retrieve_keytab_group_del) > 0 or \
len(allow_retrieve_keytab_host_del) > 0 or \
len(allow_retrieve_keytab_hostgroup_del) > 0:
commands.append(
[name, "host_disallow_retrieve_keytab",
{
"user": allow_retrieve_keytab_user_del,
"group": allow_retrieve_keytab_group_del,
"host": allow_retrieve_keytab_host_del,
"hostgroup": allow_retrieve_keytab_hostgroup_del,
}])
if len(dnsrecord_a_add) > 0 or len(dnsrecord_aaaa_add) > 0:
domain_name = name[name.find(".") + 1:]
host_name = name[:name.find(".")]
_args = {"idnsname": host_name}
if len(dnsrecord_a_add) > 0:
_args["arecord"] = dnsrecord_a_add
if reverse is not None:
_args["a_extra_create_reverse"] = reverse
if len(dnsrecord_aaaa_add) > 0:
_args["aaaarecord"] = dnsrecord_aaaa_add
if reverse is not None:
_args["aaaa_extra_create_reverse"] = reverse
commands.append([domain_name,
"dnsrecord_add", _args])
if len(dnsrecord_a_del) > 0 or len(dnsrecord_aaaa_del) > 0:
domain_name = name[name.find(".") + 1:]
host_name = name[:name.find(".")]
# There seems to be an issue with dnsrecord_del (not
# for dnsrecord_add) if aaaarecord is an empty list.
# Therefore this is done differently here:
_args = {"idnsname": host_name}
if len(dnsrecord_a_del) > 0:
_args["arecord"] = dnsrecord_a_del
if len(dnsrecord_aaaa_del) > 0:
_args["aaaarecord"] = dnsrecord_aaaa_del
commands.append([domain_name,
"dnsrecord_del", _args])
elif state == "absent":
if action == "host":
if res_find is not None:
args = {}
if update_dns is not None:
args["updatedns"] = update_dns
commands.append([name, "host_del", args])
else:
# Certificates need to be added and removed one by one,
# because if entry already exists, the processing of
# the remaining enries is stopped. The same applies to
# the removal of non-existing entries.
# Remove certificates
if certificate is not None:
for _certificate in certificate:
commands.append([name, "host_remove_cert",
{
"usercertificate":
_certificate,
}])
# Managedby_Hosts need to be added and removed one by one,
# because if entry already exists, the processing of
# the remaining enries is stopped. The same applies to
# the removal of non-existing entries.
# Remove managedby_hosts
if managedby_host is not None:
for _managedby_host in managedby_host:
commands.append([name, "host_remove_managedby",
{
"host":
_managedby_host,
}])
# Principals need to be added and removed one by one,
# because if entry already exists, the processing of
# the remaining enries is stopped. The same applies to
# the removal of non-existing entries.
# Remove principals
if principal is not None:
for _principal in principal:
commands.append([name, "host_remove_principal",
{
"krbprincipalname":
_principal,
}])
# Disallow create keytab
if allow_create_keytab_user is not None or \
allow_create_keytab_group is not None or \
allow_create_keytab_host is not None or \
allow_create_keytab_hostgroup is not None:
commands.append(
[name, "host_disallow_create_keytab",
{
"user": allow_create_keytab_user,
"group": allow_create_keytab_group,
"host": allow_create_keytab_host,
"hostgroup": allow_create_keytab_hostgroup,
}])
# Disallow retrieve keytab
if allow_retrieve_keytab_user is not None or \
allow_retrieve_keytab_group is not None or \
allow_retrieve_keytab_host is not None or \
allow_retrieve_keytab_hostgroup is not None:
commands.append(
[name, "host_disallow_retrieve_keytab",
{
"user": allow_retrieve_keytab_user,
"group": allow_retrieve_keytab_group,
"host": allow_retrieve_keytab_host,
"hostgroup": allow_retrieve_keytab_hostgroup,
}])
dnsrecord_args = gen_dnsrecord_args(ansible_module,
ip_address, reverse)
# Remove arecord and aaaarecord from dnsrecord_args
# if the record does not exits in res_find_dnsrecord
# to prevent "DNS resource record not found" error
if "arecord" in dnsrecord_args \
and dnsrecord_args["arecord"] is not None \
and len(dnsrecord_args["arecord"]) > 0 \
and (res_find_dnsrecord is None
or "arecord" not in res_find_dnsrecord):
del dnsrecord_args["arecord"]
if "aaaarecord" in dnsrecord_args \
and dnsrecord_args["aaaarecord"] is not None \
and len(dnsrecord_args["aaaarecord"]) > 0 \
and (res_find_dnsrecord is None
or "aaaarecord" not in res_find_dnsrecord):
del dnsrecord_args["aaaarecord"]
if "arecord" in dnsrecord_args or \
"aaaarecord" in dnsrecord_args:
domain_name = name[name.find(".") + 1:]
host_name = name[:name.find(".")]
dnsrecord_args["idnsname"] = host_name
commands.append([domain_name, "dnsrecord_del",
dnsrecord_args])
elif state == "disabled":
if res_find is not None:
commands.append([name, "host_disable", {}])
else:
raise ValueError("No host '%s'" % name)
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
del host_set
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, result_handler, exception_handler,
exit_args=exit_args, single_host=hosts is None)
# Done
ansible_module.exit_json(changed=changed, host=exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipahostgroup.py 0000664 0000000 0000000 00000040277 14600563364 0023645 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipahostgroup
short_description: Manage FreeIPA hostgroups
description: Manage FreeIPA hostgroups
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The hostgroup name
type: list
elements: str
required: true
aliases: ["cn"]
description:
description: The hostgroup description
type: str
required: false
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
host:
description: List of host names assigned to this hostgroup.
required: false
type: list
elements: str
hostgroup:
description: List of hostgroup names assigned to this hostgroup.
required: false
type: list
elements: str
membermanager_user:
description:
- List of member manager users assigned to this hostgroup.
- Only usable with IPA versions 4.8.4 and up.
required: false
type: list
elements: str
membermanager_group:
description:
- List of member manager groups assigned to this hostgroup.
- Only usable with IPA versions 4.8.4 and up.
required: false
type: list
elements: str
rename:
description:
- Rename hostgroup to the given name.
- Only usable with IPA versions 4.8.7 and up.
type: str
required: false
aliases: ["new_name"]
action:
description: Work on hostgroup or member level
type: str
default: hostgroup
choices: ["member", "hostgroup"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent", "renamed"]
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure host-group databases is present
- ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
# Ensure hosts and hostgroups are present in existing databases hostgroup
- ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
action: member
# Ensure hosts and hostgroups are absent in databases hostgroup
- ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
action: member
state: absent
# Rename hostgroup
- ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
rename: datalake
# Ensure host-group databases is absent
- ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
gen_intersection_list, ensure_fqdn
def find_hostgroup(module, name):
_args = {
"all": True,
"cn": name,
}
_result = module.ipa_command("hostgroup_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one hostgroup '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
return None
def gen_args(description, nomembers, rename):
_args = {}
if description is not None:
_args["description"] = description
if nomembers is not None:
_args["nomembers"] = nomembers
if rename is not None:
_args["rename"] = rename
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
description=dict(type="str", default=None),
nomembers=dict(required=False, type='bool', default=None),
host=dict(required=False, type='list', elements="str",
default=None),
hostgroup=dict(required=False, type='list', elements="str",
default=None),
membermanager_user=dict(required=False, type='list',
elements="str", default=None),
membermanager_group=dict(required=False, type='list',
elements="str", default=None),
rename=dict(required=False, type='str', default=None,
aliases=["new_name"]),
action=dict(type="str", default="hostgroup",
choices=["member", "hostgroup"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent", "renamed"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get_lowercase("name")
# present
description = ansible_module.params_get("description")
nomembers = ansible_module.params_get("nomembers")
host = ansible_module.params_get("host")
hostgroup = ansible_module.params_get_lowercase("hostgroup")
membermanager_user = ansible_module.params_get_lowercase(
"membermanager_user"
)
membermanager_group = ansible_module.params_get_lowercase(
"membermanager_group"
)
rename = ansible_module.params_get_lowercase("rename")
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one hostgroup can be added at a time.")
invalid = ["rename"]
if action == "member":
invalid.extend(["description", "nomembers"])
if state == "renamed":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one hostgroup can be added at a time.")
if action == "member":
ansible_module.fail_json(
msg="Action '%s' can not be used with state '%s'" %
(action, state))
invalid = [
"description", "nomembers", "host", "hostgroup",
"membermanager_user", "membermanager_group"
]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(
msg="No name given.")
invalid = ["description", "nomembers", "rename"]
if action == "hostgroup":
invalid.extend(["host", "hostgroup"])
ansible_module.params_fail_used_invalid(invalid, state, action)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
has_add_membermanager = ansible_module.ipa_command_exists(
"hostgroup_add_member_manager")
if ((membermanager_user is not None or
membermanager_group is not None) and not has_add_membermanager):
ansible_module.fail_json(
msg="Managing a membermanager user or group is not supported "
"by your IPA version"
)
has_mod_rename = ansible_module.ipa_command_param_exists(
"hostgroup_mod", "rename")
if not has_mod_rename and rename is not None:
ansible_module.fail_json(
msg="Renaming hostgroups is not supported by your IPA version")
# If hosts are given, ensure that the hosts are FQDN and also
# lowercase to be able to do a proper comparison to exising hosts
# in the hostgroup.
# Fixes #666 (ipahostgroup not idempotent and with error)
if host is not None:
default_domain = ansible_module.ipa_get_domain()
host = [ensure_fqdn(_host, default_domain).lower()
for _host in host]
commands = []
for name in names:
# clean add/del lists
host_add, host_del = [], []
hostgroup_add, hostgroup_del = [], []
membermanager_user_add, membermanager_user_del = [], []
membermanager_group_add, membermanager_group_del = [], []
# Make sure hostgroup exists
res_find = find_hostgroup(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description, nomembers, rename)
if action == "hostgroup":
# Found the hostgroup
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "hostgroup_mod", args])
else:
commands.append([name, "hostgroup_add", args])
# Set res_find to empty dict for next step
res_find = {}
# Generate addition and removal lists
host_add, host_del = gen_add_del_lists(
host, res_find.get("member_host")
)
hostgroup_add, hostgroup_del = gen_add_del_lists(
hostgroup, res_find.get("member_hostgroup")
)
if has_add_membermanager:
membermanager_user_add, membermanager_user_del = \
gen_add_del_lists(
membermanager_user,
res_find.get("membermanager_user")
)
membermanager_group_add, membermanager_group_del = \
gen_add_del_lists(
membermanager_group,
res_find.get("membermanager_group")
)
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No hostgroup '%s'" % name)
# Reduce add lists for member_host and member_hostgroup,
# to new entries only that are not in res_find.
host_add = gen_add_list(
host, res_find.get("member_host")
)
hostgroup_add = gen_add_list(
hostgroup, res_find.get("member_hostgroup")
)
if has_add_membermanager:
# Reduce add list for membermanager_user and
# membermanager_group to new entries only that are
# not in res_find.
membermanager_user_add = gen_add_list(
membermanager_user,
res_find.get("membermanager_user")
)
membermanager_group_add = gen_add_list(
membermanager_group,
res_find.get("membermanager_group")
)
elif state == "renamed":
if res_find is not None:
if rename != name:
commands.append(
[name, "hostgroup_mod", {"rename": rename}]
)
else:
# If a hostgroup with the desired name exists, do nothing.
new_find = find_hostgroup(ansible_module, rename)
if new_find is None:
# Fail only if the either hostsgroups do not exist.
ansible_module.fail_json(
msg="Attribute `rename` can not be used, unless "
"hostgroup exists."
)
elif state == "absent":
if action == "hostgroup":
if res_find is not None:
commands.append([name, "hostgroup_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No hostgroup '%s'" % name)
# Reduce del lists of member_host and member_hostgroup,
# to the entries only that are in res_find.
if host is not None:
host_del = gen_intersection_list(
host, res_find.get("member_host")
)
if hostgroup is not None:
hostgroup_del = gen_intersection_list(
hostgroup, res_find.get("member_hostgroup")
)
if has_add_membermanager:
# Get lists of membermanager users that exist
# in IPA and should be removed.
membermanager_user_del = gen_intersection_list(
membermanager_user,
res_find.get("membermanager_user")
)
membermanager_group_del = gen_intersection_list(
membermanager_group,
res_find.get("membermanager_group")
)
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Manage members
# Add members
if host_add or hostgroup_add:
commands.append([
name, "hostgroup_add_member",
{
"host": host_add,
"hostgroup": hostgroup_add,
}
])
# Remove members
if host_del or hostgroup_del:
commands.append([
name, "hostgroup_remove_member",
{
"host": host_del,
"hostgroup": hostgroup_del,
}
])
# Manage membermanager users and groups
if has_add_membermanager:
# Add membermanager users and groups
if membermanager_user_add or membermanager_group_add:
commands.append([
name, "hostgroup_add_member_manager",
{
"user": membermanager_user_add,
"group": membermanager_group_add,
}
])
# Remove membermanager users and groups
if membermanager_user_del or membermanager_group_del:
commands.append([
name, "hostgroup_remove_member_manager",
{
"user": membermanager_user_del,
"group": membermanager_group_del,
}
])
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaidoverridegroup.py 0000664 0000000 0000000 00000023557 14600563364 0025026 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2023 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, exither version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
# No rename support: 'ID overrides cannot be renamed'
# ipaserver/plugins/idviews.py:baseidoverride_mod:pre_callback
DOCUMENTATION = """
---
module: ipaidoverridegroup
short_description: Manage FreeIPA idoverridegroup
description: Manage FreeIPA idoverridegroups
extends_documentation_fragment:
- ipamodule_base_docs
options:
idview:
description: The idoverridegroup idview string.
type: str
required: true
aliases: ["idviewcn"]
anchor:
description: The list of anchors to override
type: list
elements: str
required: true
aliases: ["ipaanchoruuid"]
description:
description: Description
type: str
required: False
aliases: ["desc"]
name:
description: Group name
type: str
required: False
aliases: ["group_name", "cn"]
gid:
description: Group ID Number (int or "")
type: str
required: False
aliases: ["gidnumber"]
fallback_to_ldap:
description: |
Allow falling back to AD DC LDAP when resolving AD trusted objects.
For two-way trusts only.
required: False
type: bool
delete_continue:
description: |
Continuous mode. Don't stop on errors.
Valid only if `state` is `absent`.
required: false
type: bool
aliases: ["continue"]
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
type: str
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure test group test_group is present in idview test_idview
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
# Ensure test group test_group is present in idview test_idview with
# description
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
description: "test_group description"
# Ensure test group test_group is present in idview test_idview without
# description
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
description: ""
# Ensure test group test_group is present in idview test_idview with internal
# name test_123_group
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
name: test_123_group
# Ensure test group test_group is present in idview test_idview without
# internal name
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
name: ""
# Ensure test group test_group is present in idview test_idview with gid 20001
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
gid: 20001
# Ensure test group test_group is present in idview test_idview without gid
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
gid: ""
# Ensure test group test_group is absent in idview test_idview
- ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_group
continue: true
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_idoverridegroup(module, idview, anchor):
"""Find if a idoverridegroup with the given name already exist."""
try:
_result = module.ipa_command("idoverridegroup_show", idview,
{"ipaanchoruuid": anchor,
"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if idoverridegroup anchor is not found.
return None
return _result["result"]
def gen_args(anchor, description, name, gid):
# fallback_to_ldap is only a runtime tuning parameter
_args = {}
if anchor is not None:
_args["ipaanchoruuid"] = anchor
if description is not None:
_args["description"] = description
if name is not None:
_args["cn"] = name
if gid is not None:
_args["gidnumber"] = gid
return _args
def gen_args_runtime(fallback_to_ldap):
_args = {}
if fallback_to_ldap is not None:
_args["fallback_to_ldap"] = fallback_to_ldap
return _args
def merge_dicts(dict1, dict2):
ret = dict1.copy()
ret.update(dict2)
return ret
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
idview=dict(type="str", required=True, aliases=["idviewcn"]),
anchor=dict(type="list", elements="str", required=True,
aliases=["ipaanchoruuid"]),
# present
description=dict(type="str", required=False, aliases=["desc"]),
name=dict(type="str", required=False,
aliases=["group_name", "cn"]),
gid=dict(type="str", required=False, aliases=["gidnumber"]),
# runtime flags
fallback_to_ldap=dict(type="bool", required=False),
# absent
delete_continue=dict(type="bool", required=False,
aliases=['continue'], default=None),
# No rename support: 'ID overrides cannot be renamed'
# ipaserver/plugins/idviews.py:baseidoverride_mod:pre_callback
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
idview = ansible_module.params_get("idview")
anchors = ansible_module.params_get("anchor")
# present
description = ansible_module.params_get("description")
name = ansible_module.params_get("name")
gid = ansible_module.params_get_with_type_cast("gid", int)
# runtime flags
fallback_to_ldap = ansible_module.params_get("fallback_to_ldap")
# absent
delete_continue = ansible_module.params_get("delete_continue")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(anchors) != 1:
ansible_module.fail_json(
msg="Only one idoverridegroup can be added at a time.")
invalid = ["delete_continue"]
if state == "absent":
if len(anchors) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description", "name", "gid"]
ansible_module.params_fail_used_invalid(invalid, state)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
runtime_args = gen_args_runtime(fallback_to_ldap)
commands = []
for anchor in anchors:
# Make sure idoverridegroup exists
res_find = find_idoverridegroup(ansible_module, idview, anchor)
# Create command
if state == "present":
# Generate args
args = gen_args(anchor, description, name, gid)
# fallback_to_ldap is only a runtime tuning parameter
all_args = merge_dicts(args, runtime_args)
# Found the idoverridegroup
if res_find is not None:
# For idempotency: Remove empty sshpubkey list if
# there are no sshpubkey in the found entry.
if "ipasshpubkey" in args and \
len(args["ipasshpubkey"]) < 1 and \
"ipasshpubkey" not in res_find:
del args["ipasshpubkey"]
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([idview, "idoverridegroup_mod",
all_args])
else:
commands.append([idview, "idoverridegroup_add",
all_args])
elif state == "absent":
if res_find is not None:
commands.append(
[idview, "idoverridegroup_del",
merge_dicts(
{
"ipaanchoruuid": anchor,
"continue": delete_continue or False
},
runtime_args
)]
)
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaidoverrideuser.py 0000664 0000000 0000000 00000046746 14600563364 0024655 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2023 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
# No rename support: 'ID overrides cannot be renamed'
# ipaserver/plugins/idviews.py:baseidoverride_mod:pre_callback
DOCUMENTATION = """
---
module: ipaidoverrideuser
short_description: Manage FreeIPA idoverrideuser
description: Manage FreeIPA idoverrideuser and idoverrideuser members
extends_documentation_fragment:
- ipamodule_base_docs
options:
idview:
description: The idoverrideuser idview string.
type: str
required: true
aliases: ["idviewcn"]
anchor:
description: The list of anchors to override
type: list
elements: str
required: true
aliases: ["ipaanchoruuid"]
description:
description: Description
type: str
required: False
aliases: ["desc"]
name:
description: The user (internally uid)
type: str
required: False
aliases: ["login"]
uid:
description: User ID Number (int or "")
type: str
required: False
aliases: ["uidnumber"]
gecos:
description: GECOS
required: False
type: str
gidnumber:
description: Group ID Number (int or "")
required: False
type: str
homedir:
description: Home directory
type: str
required: False
aliases: ["homedirectory"]
shell:
description: Login shell
type: str
required: False
aliases: ["loginshell"]
sshpubkey:
description: List of SSH public keys
type: list
element: str
required: False
aliases: ["ipasshpubkey"]
certificate:
description: List of Base-64 encoded user certificates
type: list
elements: str
required: False
aliases: ["usercertificate"]
fallback_to_ldap:
description: |
Allow falling back to AD DC LDAP when resolving AD trusted objects.
For two-way trusts only.
required: False
type: bool
delete_continue:
description: |
Continuous mode. Don't stop on errors.
Valid only if `state` is `absent`.
required: false
type: bool
aliases: ["continue"]
nomembers:
description: |
Suppress processing of membership attributes.
Valid only if `state` is `absent`.
type: str
required: False
aliases: ["no_members"]
action:
description: Work on idoverrideuser or member level.
choices: ["idoverrideuser", "member"]
default: idoverrideuser
type: str
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
type: str
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure test user test_user is present in idview test_idview
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
# Ensure test user test_user is present in idview test_idview with description
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
description: "test_user description"
# Ensure test user test_user is present in idview test_idview without
# description
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
description: ""
# Ensure test user test_user is present in idview test_idview with internal
# name test_123_user
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
name: test_123_user
# Ensure test user test_user is present in idview test_idview without internal
# name
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
name: ""
# Ensure test user test_user is present in idview test_idview with uid 20001
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
uid: 20001
# Ensure test user test_user is present in idview test_idview without uid
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
uid: ""
# Ensure test user test_user is present in idview test_idview with gecos
# "Gecos Test"
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gecos: Gecos Test
# Ensure test user test_user is present in idview test_idview without gecos
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gecos: ""
# Ensure test user test_user is present in idview test_idview with gidnumber
# 20001
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gidnumber: 20001
# Ensure test user test_user is present in idview test_idview without
# gidnumber
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
gidnumber: ""
# Ensure test user test_user is present in idview test_idview with homedir
# /Users
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
homedir: /Users
# Ensure test user test_user is present in idview test_idview without homedir
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
homedir: ""
# Ensure test user test_user is present in idview test_idview with shell
# /bin/someshell
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
shell: /bin/someshell
# Ensure test user test_user is present in idview test_idview without shell
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
shell: ""
# Ensure test user test_user is present in idview test_idview with sshpubkey
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
sshpubkey:
- ssh-rsa AAAAB3NzaC1yc2EAAADAQABAAABgQCqmVDpEX5gnSjKuv97Ay ...
# Ensure test user test_user is present in idview test_idview without
# sshpubkey
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
sshpubkey: []
# Ensure test user test_user is present in idview test_idview with 1
# certificate
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
# Ensure test user test_user is present in idview test_idview with 3
# certificate members
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
# Ensure test user test_user is present in idview test_idview without
# 2 certificate members
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate:
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
state: absent
# Ensure test user test_user is present in idview test_idview without
# certificates
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
certificate: []
# Ensure test user test_user is absent in idview test_idview
- ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
idview: test_idview
anchor: test_user
continue: true
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
gen_intersection_list, encode_certificate
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_idoverrideuser(module, idview, anchor):
"""Find if a idoverrideuser with the given name already exist."""
try:
_result = module.ipa_command("idoverrideuser_show", idview,
{"ipaanchoruuid": anchor,
"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if idoverrideuser anchor is not found.
return None
_res = _result["result"]
certs = _res.get("usercertificate")
if certs is not None:
_res["usercertificate"] = [encode_certificate(cert) for cert in certs]
return _res
def gen_args(anchor, description, name, uid, gecos, gidnumber, homedir, shell,
sshpubkey):
# fallback_to_ldap and nomembers are only runtime tuning parameters
_args = {}
if anchor is not None:
_args["ipaanchoruuid"] = anchor
if description is not None:
_args["description"] = description
if name is not None:
_args["uid"] = name
if uid is not None:
_args["uidnumber"] = uid
if gecos is not None:
_args["gecos"] = gecos
if gidnumber is not None:
_args["gidnumber"] = gidnumber
if homedir is not None:
_args["homedirectory"] = homedir
if shell is not None:
_args["loginshell"] = shell
if sshpubkey is not None:
_args["ipasshpubkey"] = sshpubkey
return _args
def gen_args_runtime(fallback_to_ldap, nomembers):
_args = {}
if fallback_to_ldap is not None:
_args["fallback_to_ldap"] = fallback_to_ldap
if nomembers is not None:
_args["no_members"] = nomembers
return _args
def gen_member_args(certificate):
_args = {}
if certificate is not None:
_args["usercertificate"] = certificate
return _args
def merge_dicts(dict1, dict2):
ret = dict1.copy()
ret.update(dict2)
return ret
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
idview=dict(type="str", required=True, aliases=["idviewcn"]),
anchor=dict(type="list", elements="str", required=True,
aliases=["ipaanchoruuid"]),
# present
description=dict(type="str", required=False, aliases=["desc"]),
name=dict(type="str", required=False, aliases=["login"]),
uid=dict(type="str", required=False, aliases=["uidnumber"]),
gecos=dict(type="str", required=False),
gidnumber=dict(type="str", required=False),
homedir=dict(type="str", required=False,
aliases=["homedirectory"]),
shell=dict(type="str", required=False, aliases=["loginshell"]),
sshpubkey=dict(type="list", elements="str", required=False,
aliases=["ipasshpubkey"]),
certificate=dict(type="list", elements="str", required=False,
aliases=["usercertificate"]),
fallback_to_ldap=dict(type="bool", required=False),
nomembers=dict(type="bool", required=False,
aliases=["no_members"]),
# absent
delete_continue=dict(type="bool", required=False,
aliases=['continue'], default=None),
# No rename support: 'ID overrides cannot be renamed'
# ipaserver/plugins/idviews.py:baseidoverride_mod:pre_callback
# action
action=dict(type="str", default="idoverrideuser",
choices=["member", "idoverrideuser"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
idview = ansible_module.params_get("idview")
anchors = ansible_module.params_get("anchor")
# present
description = ansible_module.params_get("description")
name = ansible_module.params_get("name")
uid = ansible_module.params_get_with_type_cast("uid", int)
gecos = ansible_module.params_get("gecos")
gidnumber = ansible_module.params_get_with_type_cast("gidnumber", int)
homedir = ansible_module.params_get("homedir")
shell = ansible_module.params_get("shell")
sshpubkey = ansible_module.params_get("sshpubkey")
certificate = ansible_module.params_get("certificate")
fallback_to_ldap = ansible_module.params_get("fallback_to_ldap")
nomembers = ansible_module.params_get("nomembers")
action = ansible_module.params_get("action")
# absent
delete_continue = ansible_module.params_get("delete_continue")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(anchors) != 1:
ansible_module.fail_json(
msg="Only one idoverrideuser can be added at a time.")
invalid = ["delete_continue"]
if action == "member":
invalid += ["description", "name", "uid", "gecos", "gidnumber",
"homedir", "shell", "sshpubkey"]
if state == "absent":
if len(anchors) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description", "name", "uid", "gecos", "gidnumber",
"homedir", "shell", "sshpubkey", "nomembers"]
if action == "idoverrideuser":
invalid += ["certificate"]
ansible_module.params_fail_used_invalid(invalid, state, action)
if certificate is not None:
certificate = [cert.strip() for cert in certificate]
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
runtime_args = gen_args_runtime(fallback_to_ldap, nomembers)
commands = []
for anchor in anchors:
# Make sure idoverrideuser exists
res_find = find_idoverrideuser(ansible_module, idview, anchor)
# add/del lists
certificate_add, certificate_del = [], []
# Create command
if state == "present":
# Generate args
args = gen_args(anchor, description, name, uid, gecos,
gidnumber, homedir, shell, sshpubkey)
# fallback_to_ldap and nomembers are only runtime tuning
# parameters
all_args = merge_dicts(args, runtime_args)
if action == "idoverrideuser":
# Found the idoverrideuser
if res_find is not None:
# For idempotency: Remove empty sshpubkey list if
# there are no sshpubkey in the found entry.
if "ipasshpubkey" in args and \
len(args["ipasshpubkey"]) < 1 and \
"ipasshpubkey" not in res_find:
del args["ipasshpubkey"]
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([idview, "idoverrideuser_mod",
all_args])
else:
commands.append([idview, "idoverrideuser_add",
all_args])
res_find = {}
member_args = gen_member_args(certificate)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
certificate_add, certificate_del = gen_add_del_lists(
certificate, res_find.get("usercertificate"))
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No idoverrideuser '%s' in idview '%s'" %
(anchor, idview))
# Reduce add lists for certificate
# to new entries only that are not in res_find.
if certificate is not None:
certificate_add = gen_add_list(
certificate, res_find.get("usercertificate"))
elif state == "absent":
if action == "idoverrideuser":
if res_find is not None:
commands.append(
[idview, "idoverrideuser_del",
merge_dicts(
{
"ipaanchoruuid": anchor,
"continue": delete_continue or False
},
runtime_args
)]
)
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No idoverrideuser '%s' in idview '%s'" %
(anchor, idview))
# Reduce del lists of member_host and member_hostgroup,
# to the entries only that are in res_find.
if certificate is not None:
certificate_del = gen_intersection_list(
certificate, res_find.get("usercertificate"))
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Member management
# Add members
if certificate_add:
commands.append([idview, "idoverrideuser_add_cert",
merge_dicts(
{
"ipaanchoruuid": anchor,
"usercertificate": certificate_add
},
runtime_args
)])
# Remove members
if certificate_del:
commands.append([idview, "idoverrideuser_remove_cert",
merge_dicts(
{
"ipaanchoruuid": anchor,
"usercertificate": certificate_del
},
runtime_args
)])
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaidp.py 0000664 0000000 0000000 00000047103 14600563364 0022362 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2023 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaidp
short_description: Manage FreeIPA idp
description: Manage FreeIPA idp
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of idp name strings.
required: true
type: list
elements: str
aliases: ["cn"]
auth_uri:
description: OAuth 2.0 authorization endpoint
required: false
type: str
aliases: ["ipaidpauthendpoint"]
dev_auth_uri:
description: Device authorization endpoint
required: false
type: str
aliases: ["ipaidpdevauthendpoint"]
token_uri:
description: Token endpoint
required: false
type: str
aliases: ["ipaidptokenendpoint"]
userinfo_uri:
description: User information endpoint
required: false
type: str
aliases: ["ipaidpuserinfoendpoint"]
keys_uri:
description: JWKS endpoint
required: false
type: str
aliases: ["ipaidpkeysendpoint"]
issuer_url:
description: The Identity Provider OIDC URL
required: false
type: str
aliases: ["ipaidpissuerurl"]
client_id:
description: OAuth 2.0 client identifier
required: false
type: str
aliases: ["ipaidpclientid"]
secret:
description: OAuth 2.0 client secret
required: false
type: str
no_log: true
aliases: ["ipaidpclientsecret"]
scope:
description: OAuth 2.0 scope. Multiple scopes separated by space
required: false
type: str
aliases: ["ipaidpscope"]
idp_user_id:
description: Attribute for user identity in OAuth 2.0 userinfo
required: false
type: str
aliases: ["ipaidpsub"]
provider:
description: |
Pre-defined template string. This provides the provider defaults, which
can be overridden with the other IdP options.
required: false
type: str
choices: ["google","github","microsoft","okta","keycloak"]
aliases: ["ipaidpprovider"]
organization:
description: Organization ID or Realm name for IdP provider templates
required: false
type: str
aliases: ["ipaidporg"]
base_url:
description: Base URL for IdP provider templates
required: false
type: str
aliases: ["ipaidpbaseurl"]
rename:
description: |
New name the Identity Provider server object. Only with state: renamed.
required: false
type: str
aliases: ["new_name"]
delete_continue:
description:
Continuous mode. Don't stop on errors. Valid only if `state` is `absent`.
required: false
type: bool
aliases: ["continue"]
state:
description: The state to ensure.
choices: ["present", "absent", "renamed"]
default: present
type: str
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure keycloak idp my-keycloak-idp is present
- ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-keycloak-idp
provider: keycloak
organization: main
base_url: keycloak.idm.example.com:8443/auth
client_id: my-client-id
# Ensure google idp my-google-idp is present
- ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-google-idp
auth_uri: https://accounts.google.com/o/oauth2/auth
dev_auth_uri: https://oauth2.googleapis.com/device/code
token_uri: https://oauth2.googleapis.com/token
userinfo_uri: https://openidconnect.googleapis.com/v1/userinfo
client_id: my-client-id
scope: "openid email"
idp_user_id: email
# Ensure google idp my-google-idp is present without using provider
- ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-google-idp
provider: google
client_id: my-google-client-id
# Ensure keycloak idp my-keycloak-idp is absent
- ipaidp:
ipaadmin_password: SomeADMINpassword
name: my-keycloak-idp
delete_continue: true
state: absent
# Ensure idps my-keycloak-idp, my-github-idp and my-google-idp are absent
- ipaidp:
ipaadmin_password: SomeADMINpassword
name:
- my-keycloak-idp
- my-github-idp
- my-google-idp
delete_continue: true
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, template_str, urlparse
from ansible.module_utils import six
from copy import deepcopy
import string
from itertools import chain
if six.PY3:
unicode = str
# Copy from FreeIPA ipaserver/plugins/idp.py
idp_providers = {
'google': {
'ipaidpauthendpoint':
'https://accounts.google.com/o/oauth2/auth',
'ipaidpdevauthendpoint':
'https://oauth2.googleapis.com/device/code',
'ipaidptokenendpoint':
'https://oauth2.googleapis.com/token',
'ipaidpuserinfoendpoint':
'https://openidconnect.googleapis.com/v1/userinfo',
'ipaidpkeysendpoint':
'https://www.googleapis.com/oauth2/v3/certs',
'ipaidpscope': 'openid email',
'ipaidpsub': 'email'},
'github': {
'ipaidpauthendpoint':
'https://github.com/login/oauth/authorize',
'ipaidpdevauthendpoint':
'https://github.com/login/device/code',
'ipaidptokenendpoint':
'https://github.com/login/oauth/access_token',
'ipaidpuserinfoendpoint':
'https://api.github.com/user',
'ipaidpscope': 'user',
'ipaidpsub': 'login'},
'microsoft': {
'ipaidpauthendpoint':
'https://login.microsoftonline.com/${ipaidporg}/oauth2/v2.0/'
'authorize',
'ipaidpdevauthendpoint':
'https://login.microsoftonline.com/${ipaidporg}/oauth2/v2.0/'
'devicecode',
'ipaidptokenendpoint':
'https://login.microsoftonline.com/${ipaidporg}/oauth2/v2.0/'
'token',
'ipaidpuserinfoendpoint':
'https://graph.microsoft.com/oidc/userinfo',
'ipaidpkeysendpoint':
'https://login.microsoftonline.com/common/discovery/v2.0/keys',
'ipaidpscope': 'openid email',
'ipaidpsub': 'email',
},
'okta': {
'ipaidpauthendpoint':
'https://${ipaidpbaseurl}/oauth2/v1/authorize',
'ipaidpdevauthendpoint':
'https://${ipaidpbaseurl}/oauth2/v1/device/authorize',
'ipaidptokenendpoint':
'https://${ipaidpbaseurl}/oauth2/v1/token',
'ipaidpuserinfoendpoint':
'https://${ipaidpbaseurl}/oauth2/v1/userinfo',
'ipaidpscope': 'openid email',
'ipaidpsub': 'email'},
'keycloak': {
'ipaidpauthendpoint':
'https://${ipaidpbaseurl}/realms/${ipaidporg}/protocol/'
'openid-connect/auth',
'ipaidpdevauthendpoint':
'https://${ipaidpbaseurl}/realms/${ipaidporg}/protocol/'
'openid-connect/auth/device',
'ipaidptokenendpoint':
'https://${ipaidpbaseurl}/realms/${ipaidporg}/protocol/'
'openid-connect/token',
'ipaidpuserinfoendpoint':
'https://${ipaidpbaseurl}/realms/${ipaidporg}/protocol/'
'openid-connect/userinfo',
'ipaidpscope': 'openid email',
'ipaidpsub': 'email'},
}
def find_idp(module, name):
"""Find if a idp with the given name already exist."""
try:
_result = module.ipa_command("idp_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if idp name is not found.
return None
res = _result["result"]
# Decode binary string secret
if "ipaidpclientsecret" in res and len(res["ipaidpclientsecret"]) > 0:
res["ipaidpclientsecret"][0] = \
res["ipaidpclientsecret"][0].decode("ascii")
return res
def gen_args(auth_uri, dev_auth_uri, token_uri, userinfo_uri, keys_uri,
issuer_url, client_id, secret, scope, idp_user_id, organization,
base_url):
_args = {}
if auth_uri is not None:
_args["ipaidpauthendpoint"] = auth_uri
if dev_auth_uri is not None:
_args["ipaidpdevauthendpoint"] = dev_auth_uri
if token_uri is not None:
_args["ipaidptokenendpoint"] = token_uri
if userinfo_uri is not None:
_args["ipaidpuserinfoendpoint"] = userinfo_uri
if keys_uri is not None:
_args["ipaidpkeysendpoint"] = keys_uri
if issuer_url is not None:
_args["ipaidpissuerurl"] = issuer_url
if client_id is not None:
_args["ipaidpclientid"] = client_id
if secret is not None:
_args["ipaidpclientsecret"] = secret
if scope is not None:
_args["ipaidpscope"] = scope
if idp_user_id is not None:
_args["ipaidpsub"] = idp_user_id
if organization is not None:
_args["ipaidporg"] = organization
if base_url is not None:
_args["ipaidpbaseurl"] = base_url
return _args
# Copied and adapted from FreeIPA ipaserver/plugins/idp.py
def convert_provider_to_endpoints(module, _args, provider):
"""Convert provider option to auth-uri and token-uri,.."""
if provider not in idp_providers:
module.fail_json(msg="Provider '%s' is unknown" % provider)
# For each string in the template check if a variable
# is required, it is provided as an option
points = deepcopy(idp_providers[provider])
_r = string.Template.pattern
for (_k, _v) in points.items():
# build list of variables to be replaced
subs = list(chain.from_iterable(
(filter(None, _s) for _s in _r.findall(_v))))
if subs:
for _s in subs:
if _s not in _args:
module.fail_json(msg="Parameter '%s' is missing" % _s)
points[_k] = template_str(_v, _args)
elif _k in _args:
points[_k] = _args[_k]
_args.update(points)
def validate_uri(module, uri):
try:
parsed = urlparse(uri, 'https')
except Exception:
module.fail_json(msg="Invalid URI '%s': not an https scheme" % uri)
if not parsed.netloc:
module.fail_json(msg="Invalid URI '%s': missing netloc" % uri)
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", required=True,
aliases=["cn"]),
# present
auth_uri=dict(required=False, type="str", default=None,
aliases=["ipaidpauthendpoint"]),
dev_auth_uri=dict(required=False, type="str", default=None,
aliases=["ipaidpdevauthendpoint"]),
token_uri=dict(required=False, type="str", default=None,
aliases=["ipaidptokenendpoint"]),
userinfo_uri=dict(required=False, type="str", default=None,
aliases=["ipaidpuserinfoendpoint"]),
keys_uri=dict(required=False, type="str", default=None,
aliases=["ipaidpkeysendpoint"]),
issuer_url=dict(required=False, type="str", default=None,
aliases=["ipaidpissuerurl"]),
client_id=dict(required=False, type="str", default=None,
aliases=["ipaidpclientid"]),
secret=dict(required=False, type="str", default=None,
aliases=["ipaidpclientsecret"], no_log=True),
scope=dict(required=False, type="str", default=None,
aliases=["ipaidpscope"]),
idp_user_id=dict(required=False, type="str", default=None,
aliases=["ipaidpsub"]),
provider=dict(required=False, type="str", default=None,
aliases=["ipaidpprovider"],
choices=["google", "github", "microsoft", "okta",
"keycloak"]),
organization=dict(required=False, type="str", default=None,
aliases=["ipaidporg"]),
base_url=dict(required=False, type="str", default=None,
aliases=["ipaidpbaseurl"]),
rename=dict(required=False, type="str", default=None,
aliases=["new_name"]),
delete_continue=dict(required=False, type="bool", default=None,
aliases=['continue']),
# state
state=dict(type="str", default="present",
choices=["present", "absent", "renamed"]),
),
supports_check_mode=True,
# mutually_exclusive=[],
# required_one_of=[]
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
auth_uri = ansible_module.params_get("auth_uri")
dev_auth_uri = ansible_module.params_get("dev_auth_uri")
token_uri = ansible_module.params_get("token_uri")
userinfo_uri = ansible_module.params_get("userinfo_uri")
keys_uri = ansible_module.params_get("keys_uri")
issuer_url = ansible_module.params_get("issuer_url")
client_id = ansible_module.params_get("client_id")
secret = ansible_module.params_get("secret")
scope = ansible_module.params_get("scope")
idp_user_id = ansible_module.params_get("idp_user_id")
provider = ansible_module.params_get("provider")
organization = ansible_module.params_get("organization")
base_url = ansible_module.params_get("base_url")
rename = ansible_module.params_get("rename")
delete_continue = ansible_module.params_get("delete_continue")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one idp can be added at a time.")
if provider:
if any([auth_uri, dev_auth_uri, token_uri, userinfo_uri,
keys_uri]):
ansible_module.fail_json(
msg="Cannot specify both individual endpoints and IdP "
"provider")
if provider not in idp_providers:
ansible_module.fail_json(
msg="Provider '%s' is unknown" % provider)
invalid = ["rename", "delete_continue"]
else:
# state renamed and absent
invalid = ["auth_uri", "dev_auth_uri", "token_uri", "userinfo_uri",
"keys_uri", "issuer_url", "client_id", "secret", "scope",
"idp_user_id", "provider", "organization", "base_url"]
if state == "renamed":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one permission can be renamed at a time.")
invalid += ["delete_continue"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid += ["rename"]
ansible_module.params_fail_used_invalid(invalid, state)
# Empty client_id test
if client_id is not None and client_id == "":
ansible_module.fail_json(msg="'client_id' is required")
# Normalize base_url
if base_url is not None and base_url.startswith('https://'):
base_url = base_url[len('https://'):]
# Validate uris
for uri in [auth_uri, dev_auth_uri, token_uri, userinfo_uri, keys_uri]:
if uri is not None and uri != "":
validate_uri(ansible_module, uri)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
if not ansible_module.ipa_command_exists("idp_add"):
ansible_module.fail_json(
msg="Managing idp is not supported by your IPA version")
commands = []
for name in names:
# Make sure idp exists
res_find = find_idp(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(auth_uri, dev_auth_uri, token_uri,
userinfo_uri, keys_uri, issuer_url, client_id,
secret, scope, idp_user_id, organization,
base_url)
if provider is not None:
convert_provider_to_endpoints(ansible_module, args,
provider)
# Found the idp
if res_find is not None:
# The parameters ipaidpprovider, ipaidporg and
# ipaidpbaseurl are only available for idp-add to create
# then endpoints using provider, Therefore we have to
# remove them from args.
for arg in ["ipaidpprovider", "ipaidporg",
"ipaidpbaseurl"]:
if arg in args:
del args[arg]
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "idp_mod", args])
else:
if "ipaidpauthendpoint" not in args:
ansible_module.fail_json(
msg="Parameter '%s' is missing" % "auth_uri")
if "ipaidpdevauthendpoint" not in args:
ansible_module.fail_json(
msg="Parameter '%s' is missing" % "dev_auth_uri")
if "ipaidptokenendpoint" not in args:
ansible_module.fail_json(
msg="Parameter '%s' is missing" % "token_uri")
if "ipaidpuserinfoendpoint" not in args:
ansible_module.fail_json(
msg="Parameter '%s' is missing" % "userinfo_uri")
commands.append([name, "idp_add", args])
elif state == "absent":
if res_find is not None:
_args = {}
if delete_continue is not None:
_args = {"continue": delete_continue}
commands.append([name, "idp_del", _args])
elif state == "renamed":
if not rename:
ansible_module.fail_json(msg="No rename value given.")
if res_find is None:
ansible_module.fail_json(
msg="No idp found to be renamed: '%s'" % (name))
if name != rename:
commands.append(
[name, "idp_mod", {"rename": rename}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaidrange.py 0000664 0000000 0000000 00000025503 14600563364 0023217 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
# Thomas Woerner
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaidrange
short_description: Manage FreeIPA idrange
description: Manage FreeIPA idrange
extends_documentation_fragment:
- ipamodule_base_docs
- ipamodule_base_docs.delete_continue
options:
name:
description: The list of idrange name strings.
type: list
elements: str
required: true
aliases: ["cn"]
base_id:
description: First Posix ID of the range.
type: int
required: false
aliases: ["ipabaseid"]
range_size:
description: Number of IDs in the range.
type: int
required: false
aliases: ["ipaidrangesize"]
rid_base:
description: First RID of the corresponding RID range.
type: int
required: false
aliases: ["ipabaserid"]
secondary_rid_base:
description: First RID of the secondary RID range.
type: int
required: false
aliases: ["ipasecondarybaserid"]
idrange_type:
description: ID range type.
type: str
required: false
choices: ["ipa-ad-trust", "ipa-ad-trust-posix", "ipa-local"]
aliases: ["iparangetype"]
dom_sid:
description: Domain SID of the trusted domain.
type: str
required: false
aliases: ["ipanttrusteddomainsid"]
dom_name:
description: |
Domain name of the trusted domain. Can only be used when
`ipaapi_context: server`.
type: str
required: false
aliases: ["ipanttrusteddomainname"]
auto_private_groups:
description: Auto creation of private groups.
type: str
required: false
choices: ["true", "false", "hybrid"]
aliases: ["ipaautoprivategroups"]
state:
description: The state to ensure.
type: str
choices: ["present", "absent"]
default: present
required: false
author:
- Rafael Guterres Jeffman (@rjeffman)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure local domain idrange is present
- ipaidrange:
ipaadmin_password: SomeADMINpassword
name: id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
secondary_rid_base: 200000000
# Ensure local domain idrange is absent
- ipaidrange:
ipaadmin_password: SomeADMINpassword
name: id_range
state: absent
# Ensure AD-trust idrange is present
- ipaidrange:
name: id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
idrange_type: ipa-ad-trust
dom_sid: S-1-5-21-2870384104-3340008087-3140804251
auto_private_groups: "false"
# Ensure AD-trust idrange is present, with range type ad-trust-posix,
# and using domain name
- ipaidrange:
name: id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
idrange_type: ipa-ad-trust-posix
dom_name: ad.ipa.test
auto_private_groups: "hybrid"
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, get_trusted_domain_sid_from_name
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_idrange(module, name):
"""Find if a idrange with the given name already exist."""
try:
_result = module.ipa_command("idrange_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if idrange name is not found.
return None
return _result["result"]
def gen_args(
base_id, range_size, rid_base, secondary_rid_base, idrange_type, dom_sid,
dom_name, auto_private_groups
):
_args = {}
# Integer parameters are stored as strings.
# Converting them here allows the proper use of compare_args_ipa.
if base_id is not None:
_args["ipabaseid"] = base_id
if range_size is not None:
_args["ipaidrangesize"] = range_size
if rid_base is not None:
_args["ipabaserid"] = rid_base
if secondary_rid_base is not None:
_args["ipasecondarybaserid"] = secondary_rid_base
if idrange_type is not None:
_args["iparangetype"] = idrange_type
if dom_name is not None:
dom_sid = get_trusted_domain_sid_from_name(dom_name)
if dom_sid is not None:
_args["ipanttrusteddomainsid"] = dom_sid
if auto_private_groups is not None:
_args["ipaautoprivategroups"] = auto_private_groups
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
base_id=dict(required=False, type='int',
aliases=["ipabaseid"], default=None),
range_size=dict(required=False, type='int',
aliases=["ipaidrangesize"], default=None),
rid_base=dict(required=False, type='int',
aliases=["ipabaserid"], default=None),
secondary_rid_base=dict(required=False, type='int', default=None,
aliases=["ipasecondarybaserid"]),
idrange_type=dict(required=False, aliases=["iparangetype"],
type="str", default=None,
choices=["ipa-ad-trust", "ipa-ad-trust-posix",
"ipa-local"]),
dom_sid=dict(required=False, type='str', default=None,
aliases=["ipanttrusteddomainsid"]),
dom_name=dict(required=False, type='str', default=None,
aliases=["ipanttrusteddomainname"]),
auto_private_groups=dict(required=False, type='str', default=None,
aliases=["ipaautoprivategroups"],
choices=['true', 'false', 'hybrid']),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
mutually_exclusive=[
["dom_sid", "secondary_rid_base"],
["dom_name", "secondary_rid_base"],
["dom_sid", "dom_name"],
],
supports_check_mode=True,
ipa_module_options=["delete_continue"],
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
delete_continue = ansible_module.params_get("delete_continue")
# present
base_id = ansible_module.params_get("base_id")
range_size = ansible_module.params_get("range_size")
rid_base = ansible_module.params_get("rid_base")
secondary_rid_base = ansible_module.params_get("secondary_rid_base")
idrange_type = ansible_module.params_get("idrange_type")
dom_sid = ansible_module.params_get("dom_sid")
dom_name = ansible_module.params_get("dom_name")
auto_private_groups = \
ansible_module.params_get_lowercase("auto_private_groups")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one idrange can be added at a time.")
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = [
"base_id", "range_size", "idrange_type", "dom_sid", "dom_name",
"rid_base", "secondary_rid_base", "auto_private_groups"
]
ansible_module.params_fail_used_invalid(invalid, state)
# Init
changed = False
exit_args = {}
range_types = {
"Active Directory domain range": "ipa-ad-trust",
"Active Directory trust range with POSIX attributes":
"ipa-ad-trust-posix",
"local domain range": "ipa-local",
}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
# Make sure idrange exists
res_find = find_idrange(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(
base_id, range_size, rid_base, secondary_rid_base,
idrange_type, dom_sid, dom_name, auto_private_groups
)
# Found the idrange
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(
ansible_module, args, res_find, ignore=["iparangetype"]
):
res_type = range_types.get(
res_find.get("iparangetype")[0]
)
if res_type == "local_id_range":
ansible_module.fail_json(
"Cannot modify local IPA domain idrange."
)
arg_type = args.get("iparangetype")
if arg_type:
if arg_type != res_type:
ansible_module.fail_json(
"Cannot modify idrange type."
)
del args["iparangetype"]
commands.append([name, "idrange_mod", args])
else:
commands.append([name, "idrange_add", args])
elif state == "absent":
if res_find is not None:
commands.append([
name,
"idrange_del",
{"continue": delete_continue or False}
])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaidview.py 0000664 0000000 0000000 00000026345 14600563364 0023102 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2023 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaidview
short_description: Manage FreeIPA idview
description: Manage FreeIPA idview and idview host members
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of idview name strings.
required: true
type: list
elements: str
aliases: ["cn"]
description:
description: Description
required: False
type: str
aliases: ["desc"]
domain_resolution_order:
description: |
Colon-separated list of domains used for short name qualification
required: False
type: str
aliases: ["ipadomainresolutionorder"]
host:
description: Hosts to apply the ID View to
required: False
type: list
elements: str
aliases: ["hosts"]
rename:
description: Rename the ID view object
required: False
type: str
aliases: ["new_name"]
delete_continue:
description: |
Continuous mode. Don't stop on errors.
Valid only if `state` is `absent`.
required: false
type: bool
aliases: ["continue"]
action:
description: Work on idview or member level.
choices: ["idview", "member"]
default: idview
type: str
state:
description: The state to ensure.
choices: ["present", "absent", "renamed"]
default: present
type: str
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure idview test_idview is present
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
# name: Ensure host testhost.example.com is applied to idview test_idview
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
host: testhost.example.com
action: member
# Ensure host testhost.example.com is not applied to idview test_idview
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
host: testhost.example.com
action: member
state: absent
# Ensure idview "test_idview" is present with domain_resolution_order for
# "ad.example.com:ipa.example.com"
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
domain_resolution_order: "ad.example.com:ipa.example.com"
# Ensure idview test_idview is absent
- ipaidview:
ipaadmin_password: SomeADMINpassword
name: test_idview
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
gen_intersection_list, ipalib_errors
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_idview(module, name):
"""Find if a idview with the given name already exist."""
try:
_result = module.ipa_command("idview_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if idview name is not found.
return None
return _result["result"]
def valid_host(module, name):
try:
module.ipa_command("host_show", name, {})
except ipalib_errors.NotFound:
return False
return True
def gen_args(description, domain_resolution_order):
_args = {}
if description is not None:
_args["description"] = description
if domain_resolution_order is not None:
_args["ipadomainresolutionorder"] = domain_resolution_order
return _args
def gen_member_args(host):
_args = {}
if host is not None:
_args["host"] = host
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", required=True,
aliases=["cn"]),
# present
description=dict(type="str", required=False, aliases=["desc"]),
domain_resolution_order=dict(type="str", required=False,
aliases=["ipadomainresolutionorder"]),
host=dict(type="list", elements="str", required=False,
aliases=["hosts"], default=None),
rename=dict(type="str", required=False, aliases=["new_name"]),
delete_continue=dict(type="bool", required=False,
aliases=['continue'], default=None),
# action
action=dict(type="str", default="idview",
choices=["member", "idview"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent", "renamed"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
description = ansible_module.params_get("description")
domain_resolution_order = ansible_module.params_get(
"domain_resolution_order")
host = ansible_module.params_get("host")
rename = ansible_module.params_get("rename")
action = ansible_module.params_get("action")
# absent
delete_continue = ansible_module.params_get("delete_continue")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one idview can be added at a time.")
invalid = ["delete_continue", "rename"]
if action == "member":
invalid += ["description", "domain_resolution_order"]
if state == "renamed":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one idoverridegroup can be renamed at a time.")
if not rename:
ansible_module.fail_json(
msg="Rename is required for state: renamed.")
if action == "member":
ansible_module.fail_json(
msg="Action member can not be used with state: renamed.")
invalid = ["description", "domain_resolution_order", "host",
"delete_continue"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description", "domain_resolution_order", "rename"]
if action == "idview":
invalid += ["host"]
ansible_module.params_fail_used_invalid(invalid, state, action)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
# Make sure idview exists
res_find = find_idview(ansible_module, name)
# add/del lists
host_add, host_del = [], []
# Create command
if state == "present":
# Generate args
args = gen_args(description, domain_resolution_order)
if action == "idview":
# Found the idview
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "idview_mod", args])
else:
commands.append([name, "idview_add", args])
res_find = {}
member_args = gen_member_args(host)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
host_add, host_del = gen_add_del_lists(
host, res_find.get("appliedtohosts"))
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No idview '%s'" % name)
# Reduce add lists for host
# to new entries only that are not in res_find.
if host is not None:
host_add = gen_add_list(
host, res_find.get("appliedtohosts"))
elif state == "absent":
if action == "idview":
if res_find is not None:
commands.append(
[name, "idview_del",
{"continue": delete_continue or False}]
)
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No idview '%s'" % name)
# Reduce del lists of member_host
# to the entries only that are in res_find.
if host is not None:
host_del = gen_intersection_list(
host, res_find.get("appliedtohosts"))
elif state == "renamed":
if res_find is None:
ansible_module.fail_json(msg="No idview '%s'" % name)
else:
commands.append([name, 'idview_mod', {"rename": rename}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Member management
# Add members
if host_add:
for host in host_add:
if not valid_host(ansible_module, host):
ansible_module.fail_json("Invalid host '%s'" % host)
commands.append([name, "idview_apply", {"host": host_add}])
# Remove members
if host_del:
# idview_unapply does not have the idview name (cn) as an arg.
# It is removing the host from any idview it is applied to.
# But as we create the intersection with the list of hosts of
# the idview, we emulate the correct behaviour. But this means
# that there is no general idview_unapply like in the cli.
commands.append([None, "idview_unapply", {"host": host_del}])
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipalocation.py 0000664 0000000 0000000 00000011633 14600563364 0023415 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2020-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipalocation
short_description: Manage FreeIPA location
description: Manage FreeIPA location
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of location name strings.
type: list
elements: str
required: true
aliases: ["idnsname"]
description:
description: The IPA location string
type: str
required: false
state:
description: The state to ensure.
type: str
choices: ["present", "absent"]
default: present
required: false
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure location my_location1 is present
- ipalocation:
ipaadmin_password: SomeADMINpassword
name: my_location1
description: My location 1
# Ensure location my_location1 is absent
- ipalocation:
ipaadmin_password: SomeADMINpassword
name: my_location1
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
def find_location(module, name):
"""Find if a location with the given name already exist."""
try:
_result = module.ipa_command("location_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if location name is not found.
return None
return _result["result"]
def gen_args(description):
_args = {}
if description is not None:
_args["description"] = description
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
name=dict(type="list", elements="str", aliases=["idnsname"],
required=True),
# present
description=dict(required=False, type='str', default=None),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
description = ansible_module.params_get("description")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one location be added at a time.")
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description"]
ansible_module.params_fail_used_invalid(invalid, state)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
# Make sure location exists
res_find = find_location(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description)
# Found the location
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "location_mod", args])
else:
commands.append([name, "location_add", args])
elif state == "absent":
if res_find is not None:
commands.append([name, "location_del", {}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipanetgroup.py 0000664 0000000 0000000 00000034537 14600563364 0023460 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Denis Karpelevich
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipanetgroup
short_description: NIS entities can be stored in netgroups.
description: |
A netgroup is a group used for permission checking.
It can contain both user and host values.
extends_documentation_fragment:
- ipamodule_base_docs
- ipamodule_base_docs.delete_continue
options:
name:
description: The list of netgroup name strings.
required: true
type: list
elements: str
aliases: ["cn"]
description:
description: Netgroup description
required: false
type: str
aliases: ["desc"]
nisdomain:
description: NIS domain name
required: false
type: str
aliases: ["nisdomainname"]
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
user:
description: List of user names assigned to this netgroup.
required: false
type: list
elements: str
aliases: ["users"]
group:
description: List of group names assigned to this netgroup.
required: false
type: list
elements: str
aliases: ["groups"]
host:
description: List of host names assigned to this netgroup.
required: false
type: list
elements: str
aliases: ["hosts"]
hostgroup:
description: List of host group names assigned to this netgroup.
required: false
type: list
elements: str
aliases: ["hostgroups"]
netgroup:
description: List of netgroup names assigned to this netgroup.
required: false
type: list
elements: str
aliases: ["netgroups"]
action:
description: Work on netgroup or member level
required: false
type: str
default: netgroup
choices: ["member", "netgroup"]
state:
description: The state to ensure.
type: str
choices: ["present", "absent"]
default: present
author:
- Denis Karpelevich (@dkarpele)
"""
EXAMPLES = """
- name: Ensure netgroup my_netgroup1 is present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: my_netgroup1
description: My netgroup 1
- name: Ensure netgroup my_netgroup1 is absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: my_netgroup1
state: absent
- name: Ensure netgroup is present with user "user1"
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: TestNetgroup1
user: user1
action: member
- name: Ensure netgroup user, "user1", is absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: TestNetgroup1
user: "user1"
action: member
state: absent
- name: Ensure netgroup is present with members
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: TestNetgroup1
user: user1,user2
group: group1
host: host1
hostgroup: ipaservers
netgroup: admins
action: member
- name: Ensure 2 netgroups TestNetgroup1, admins are absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name:
- TestNetgroup1
- admins
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, \
gen_add_list, gen_intersection_list, ensure_fqdn
def find_netgroup(module, name):
"""Find if a netgroup with the given name already exist."""
_args = {
"all": True,
"cn": name,
}
# `netgroup_find` is used here instead of `netgroup_show` to workaround
# FreeIPA bug https://pagure.io/freeipa/issue/9284.
# `ipa netgroup-show hostgroup` shows hostgroup - it's a bug.
# `ipa netgroup-find hostgroup` doesn't show hostgroup - it's correct.
_result = module.ipa_command("netgroup_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one netgroup '%s'" % name)
elif len(_result["result"]) == 1:
return _result["result"][0]
return None
def gen_args(description, nisdomain, nomembers):
_args = {}
if description is not None:
_args["description"] = description
if nisdomain is not None:
_args["nisdomainname"] = nisdomain
if nomembers is not None:
_args["nomembers"] = nomembers
return _args
def gen_member_args(user, group, host, hostgroup, netgroup):
_args = {}
if user is not None:
_args["memberuser_user"] = user
if group is not None:
_args["memberuser_group"] = group
if host is not None:
_args["memberhost_host"] = host
if hostgroup is not None:
_args["memberhost_hostgroup"] = hostgroup
if netgroup is not None:
_args["member_netgroup"] = netgroup
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
description=dict(required=False, type='str',
aliases=["desc"], default=None),
nisdomain=dict(required=False, type='str',
aliases=["nisdomainname"], default=None),
nomembers=dict(required=False, type='bool', default=None),
user=dict(required=False, type='list', elements="str",
aliases=["users"], default=None),
group=dict(required=False, type='list', elements="str",
aliases=["groups"], default=None),
host=dict(required=False, type='list', elements="str",
aliases=["hosts"], default=None),
hostgroup=dict(required=False, type='list', elements="str",
aliases=["hostgroups"], default=None),
netgroup=dict(required=False, type='list', elements="str",
aliases=["netgroups"], default=None),
action=dict(required=False, type="str", default="netgroup",
choices=["member", "netgroup"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
ipa_module_options=["delete_continue"],
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
description = ansible_module.params_get("description")
nisdomain = ansible_module.params_get("nisdomain")
nomembers = ansible_module.params_get("nomembers")
user = ansible_module.params_get_lowercase("user")
group = ansible_module.params_get_lowercase("group")
host = ansible_module.params_get_lowercase("host")
hostgroup = ansible_module.params_get_lowercase("hostgroup")
netgroup = ansible_module.params_get_lowercase("netgroup")
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one netgroup can be added at a time.")
if action == "member":
invalid = ["description", "nisdomain", "nomembers"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
if len(names) != 1 and action == "member":
ansible_module.fail_json(msg="Members can be removed only from one"
" netgroup at a time.")
invalid = ["description", "nisdomain", "nomembers"]
if action == "netgroup":
invalid.extend(["user", "group", "host", "hostgroup", "netgroup"])
ansible_module.params_fail_used_invalid(invalid, state)
# Init
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
# Ensure fqdn host names, use default domain for simple names
if host is not None:
default_domain = ansible_module.ipa_get_domain()
host = [ensure_fqdn(_host, default_domain).lower()
for _host in host]
commands = []
for name in names:
# Make sure netgroup exists
res_find = find_netgroup(ansible_module, name)
user_add, user_del = [], []
group_add, group_del = [], []
host_add, host_del = [], []
hostgroup_add, hostgroup_del = [], []
netgroup_add, netgroup_del = [], []
# Create command
if state == "present":
# Generate args
args = gen_args(description, nisdomain, nomembers)
if action == "netgroup":
# Found the netgroup
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "netgroup_mod", args])
else:
commands.append([name, "netgroup_add", args])
res_find = {}
member_args = gen_member_args(
user, group, host, hostgroup, netgroup
)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
user_add, user_del = gen_add_del_lists(
user, res_find.get("memberuser_user"))
group_add, group_del = gen_add_del_lists(
group, res_find.get("memberuser_group"))
host_add, host_del = gen_add_del_lists(
host, res_find.get("memberhost_host"))
hostgroup_add, hostgroup_del = gen_add_del_lists(
hostgroup, res_find.get("memberhost_hostgroup"))
netgroup_add, netgroup_del = gen_add_del_lists(
netgroup, res_find.get("member_netgroup"))
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No netgroup '%s'" % name)
# Reduce add lists for memberuser_user, memberuser_group,
# member_service and member_external to new entries
# only that are not in res_find.
user_add = gen_add_list(
user, res_find.get("memberuser_user"))
group_add = gen_add_list(
group, res_find.get("memberuser_group"))
host_add = gen_add_list(
host, res_find.get("memberhost_host"))
hostgroup_add = gen_add_list(
hostgroup, res_find.get("memberhost_hostgroup"))
netgroup_add = gen_add_list(
netgroup, res_find.get("member_netgroup"))
elif state == "absent":
if action == "netgroup":
if res_find is not None:
commands.append([name, "netgroup_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No netgroup '%s'" % name)
user_del = gen_intersection_list(
user, res_find.get("memberuser_user"))
group_del = gen_intersection_list(
group, res_find.get("memberuser_group"))
host_del = gen_intersection_list(
host, res_find.get("memberhost_host"))
hostgroup_del = gen_intersection_list(
hostgroup, res_find.get("memberhost_hostgroup"))
netgroup_del = gen_intersection_list(
netgroup, res_find.get("member_netgroup"))
else:
ansible_module.fail_json(msg="Unknown state '%s'" % state)
# manage members
# setup member args for add/remove members.
add_member_args = {
"user": user_add,
"group": group_add,
"host": host_add,
"hostgroup": hostgroup_add,
"netgroup": netgroup_add
}
del_member_args = {
"user": user_del,
"group": group_del,
"host": host_del,
"hostgroup": hostgroup_del,
"netgroup": netgroup_del
}
# Add members
add_members = any([user_add, group_add, host_add,
hostgroup_add, netgroup_add])
if add_members:
commands.append(
[name, "netgroup_add_member", add_member_args]
)
# Remove members
remove_members = any([user_del, group_del, host_del,
hostgroup_del, netgroup_del])
if remove_members:
commands.append(
[name, "netgroup_remove_member", del_member_args]
)
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipapermission.py 0000664 0000000 0000000 00000042324 14600563364 0023776 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Seth Kress
# Thomas Woerner
#
# Copyright (C) 2020-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipapermission
short_description: Manage FreeIPA permission
description: Manage FreeIPA permission and permission members
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The permission name string.
type: list
elements: str
required: true
aliases: ["cn"]
right:
description: Rights to grant
required: false
choices: ["read", "search", "compare", "write", "add", "delete", "all"]
type: list
elements: str
aliases: ["ipapermright"]
attrs:
description: All attributes to which the permission applies
required: false
type: list
elements: str
bindtype:
description: Bind rule type
required: false
type: str
choices: ["permission", "all", "anonymous", "self"]
aliases: ["ipapermbindruletype"]
subtree:
description: Subtree to apply permissions to
type: str
required: false
aliases: ["ipapermlocation"]
extra_target_filter:
description: Extra target filter
required: false
type: list
elements: str
aliases: ["filter", "extratargetfilter"]
rawfilter:
description: All target filters
required: false
type: list
elements: str
aliases: ["ipapermtargetfilter"]
target:
description: Optional DN to apply the permission to
type: str
required: false
aliases: ["ipapermtarget"]
targetto:
description: Optional DN subtree where an entry can be moved to
type: str
required: false
aliases: ["ipapermtargetto"]
targetfrom:
description: Optional DN subtree from where an entry can be moved
type: str
required: false
aliases: ["ipapermtargetfrom"]
memberof:
description: Target members of a group (sets memberOf targetfilter)
required: false
type: list
elements: str
targetgroup:
description: User group to apply permissions to (sets target)
type: str
required: false
aliases: ["targetgroup"]
object_type:
description: Type of IPA object (sets subtree and objectClass targetfilter)
type: str
required: false
aliases: ["type"]
no_members:
description: Suppress processing of membership
required: false
type: bool
rename:
description: Rename the permission object
type: str
required: false
aliases: ["new_name"]
action:
description: Work on permission or member privilege level.
type: str
choices: ["permission", "member"]
default: permission
required: false
state:
description: The state to ensure.
type: str
choices: ["present", "absent", "renamed"]
default: present
required: false
author:
- Seth Kress (@kresss)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure permission NAME is present
- ipapermission:
name: manage-my-hostgroup
right: all
bindtype: permission
object_type: host
# Ensure permission NAME is absent
- ipapermission:
name: "Removed Permission Name"
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
def find_permission(module, name):
"""Find if a permission with the given name already exist."""
try:
_result = module.ipa_command("permission_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if permission name is not found.
return None
return _result["result"]
def gen_args(right, attrs, bindtype, subtree,
extra_target_filter, rawfilter, target,
targetto, targetfrom, memberof, targetgroup,
object_type, no_members, rename):
_args = {}
if right is not None:
_args["ipapermright"] = right
if attrs is not None:
_args["attrs"] = attrs
if bindtype is not None:
_args["ipapermbindruletype"] = bindtype
if subtree is not None:
_args["ipapermlocation"] = subtree
if extra_target_filter is not None:
_args["extratargetfilter"] = extra_target_filter
if rawfilter is not None:
_args["ipapermtargetfilter"] = rawfilter
if target is not None:
_args["ipapermtarget"] = target
if targetto is not None:
_args["ipapermtargetto"] = targetto
if targetfrom is not None:
_args["ipapermtargetfrom"] = targetfrom
if memberof is not None:
_args["memberof"] = memberof
if targetgroup is not None:
_args["targetgroup"] = targetgroup
if object_type is not None:
_args["type"] = object_type
if no_members is not None:
_args["no_members"] = no_members
if rename is not None:
_args["rename"] = rename
return _args
# pylint: disable=unused-argument
def result_handler(module, result, command, name, args, errors):
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
for failed_item in result.get("failed", []):
failed = result["failed"][failed_item]
for member_type in failed:
for member, failure in failed[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
right=dict(type="list", elements="str", aliases=["ipapermright"],
default=None, required=False,
choices=["read", "search", "compare", "write", "add",
"delete", "all"]),
attrs=dict(type="list", elements="str", default=None,
required=False),
# Note: bindtype has a default of permission for Adds.
bindtype=dict(type="str", aliases=["ipapermbindruletype"],
default=None, required=False, choices=["permission",
"all", "anonymous", "self"]),
subtree=dict(type="str", aliases=["ipapermlocation"], default=None,
required=False),
extra_target_filter=dict(type="list", elements="str",
aliases=["filter", "extratargetfilter"],
default=None, required=False),
rawfilter=dict(type="list", elements="str",
aliases=["ipapermtargetfilter"],
default=None, required=False),
target=dict(type="str", aliases=["ipapermtarget"], default=None,
required=False),
targetto=dict(type="str", aliases=["ipapermtargetto"],
default=None, required=False),
targetfrom=dict(type="str", aliases=["ipapermtargetfrom"],
default=None, required=False),
memberof=dict(type="list", elements="str", default=None,
required=False),
targetgroup=dict(type="str", default=None, required=False),
object_type=dict(type="str", aliases=["type"], default=None,
required=False),
no_members=dict(type="bool", default=None, required=False),
rename=dict(type="str", default=None, required=False,
aliases=["new_name"]),
action=dict(type="str", default="permission",
choices=["member", "permission"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent", "renamed"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
right = ansible_module.params_get("right")
attrs = ansible_module.params_get("attrs")
bindtype = ansible_module.params_get("bindtype")
subtree = ansible_module.params_get("subtree")
extra_target_filter = ansible_module.params_get("extra_target_filter")
rawfilter = ansible_module.params_get("rawfilter")
target = ansible_module.params_get("target")
targetto = ansible_module.params_get("targetto")
targetfrom = ansible_module.params_get("targetfrom")
memberof = ansible_module.params_get("memberof")
targetgroup = ansible_module.params_get("targetgroup")
object_type = ansible_module.params_get("object_type")
no_members = ansible_module.params_get("no_members")
rename = ansible_module.params_get("rename")
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one permission can be added at a time.")
if action == "member":
invalid = ["bindtype", "target", "targetto", "targetfrom",
"subtree", "targetgroup", "object_type", "rename"]
else:
invalid = ["rename"]
if state == "renamed":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one permission can be renamed at a time.")
if action == "member":
ansible_module.fail_json(
msg="Member action can not be used with state 'renamed'")
invalid = ["right", "attrs", "bindtype", "subtree",
"extra_target_filter", "rawfilter", "target", "targetto",
"targetfrom", "memberof", "targetgroup", "object_type",
"no_members"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["bindtype", "subtree", "target", "targetto",
"targetfrom", "targetgroup", "object_type",
"no_members", "rename"]
if action != "member":
invalid += ["right", "attrs", "memberof",
"extra_target_filter", "rawfilter"]
ansible_module.params_fail_used_invalid(invalid, state, action)
if bindtype == "self" and ansible_module.ipa_check_version("<", "4.8.7"):
ansible_module.fail_json(
msg="Bindtype 'self' is not supported by your IPA version.")
if all([extra_target_filter, rawfilter]):
ansible_module.fail_json(
msg="Cannot specify target filter and extra target filter "
"simultaneously.")
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
# Make sure permission exists
res_find = find_permission(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(right, attrs, bindtype, subtree,
extra_target_filter, rawfilter, target,
targetto, targetfrom, memberof, targetgroup,
object_type, no_members, rename)
if action == "permission":
# Found the permission
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "permission_mod", args])
else:
commands.append([name, "permission_add", args])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No permission '%s'" % name)
member_attrs = {}
check_members = {
"attrs": attrs,
"memberof": memberof,
"ipapermright": right,
"ipapermtargetfilter": rawfilter,
"extratargetfilter": extra_target_filter,
# subtree member management is currently disabled.
# "ipapermlocation": subtree,
}
for _member, _member_change in check_members.items():
if _member_change is not None:
_res_list = res_find[_member]
# if running in a client context, data may be
# returned as a tuple instead of a list.
if isinstance(_res_list, tuple):
_res_list = list(_res_list)
_new_set = set(_res_list + _member_change)
if _new_set != set(_res_list):
member_attrs[_member] = list(_new_set)
if member_attrs:
commands.append([name, "permission_mod", member_attrs])
else:
ansible_module.fail_json(
msg="Unknown action '%s'" % action)
elif state == "renamed":
if action == "permission":
# Generate args
# Note: Only valid arg for rename is rename.
args = gen_args(right, attrs, bindtype, subtree,
extra_target_filter, rawfilter, target,
targetto, targetfrom, memberof,
targetgroup, object_type, no_members,
rename)
# Found the permission
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "permission_mod", args])
else:
ansible_module.fail_json(
msg="Permission not found, cannot rename")
else:
ansible_module.fail_json(
msg="Unknown action '%s'" % action)
elif state == "absent":
if action == "permission":
if res_find is not None:
commands.append([name, "permission_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No permission '%s'" % name)
member_attrs = {}
check_members = {
"attrs": attrs,
"memberof": memberof,
"ipapermright": right,
"ipapermtargetfilter": rawfilter,
"extratargetfilter": extra_target_filter,
# subtree member management is currently disabled.
# "ipapermlocation": subtree,
}
for _member, _member_change in check_members.items():
if _member_change is not None:
_res_set = set(res_find[_member])
_new_set = _res_set - set(_member_change)
if _new_set != _res_set:
member_attrs[_member] = list(_new_set)
if member_attrs:
commands.append([name, "permission_mod", member_attrs])
else:
ansible_module.fail_json(msg="Unknown state '%s'" % state)
# Execute commands
changed = ansible_module.execute_ipa_commands(commands, result_handler)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaprivilege.py 0000664 0000000 0000000 00000023524 14600563364 0023575 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
# Thomas Woerner
#
# Copyright (C) 2020-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
"""ansible-freeipa module to manage FreeIPA privileges."""
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaprivilege
short_description: Manage FreeIPA privilege
description: Manage FreeIPA privilege and privilege members
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of privilege name strings.
type: list
elements: str
required: true
aliases: ["cn"]
description:
description: Privilege description
type: str
required: false
rename:
description: Rename the privilege object.
type: str
required: false
aliases: ["new_name"]
permission:
description: Permissions to be added to the privilege.
type: list
elements: str
required: false
action:
description: Work on privilege or member level.
type: str
choices: ["privilege", "member"]
default: privilege
required: false
state:
description: The state to ensure.
type: str
choices: ["present", "absent", "renamed"]
default: present
required: false
author:
- Rafael Guterres Jeffman (@rjeffman)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure privilege "Broad Privilege" is present
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
description: Broad Privilege
# Ensure privilege "Broad Privilege" has permissions set
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
permission:
- "Write IPA Configuration"
- "System: Write DNS Configuration"
- "System: Update DNS Entries"
action: member
# Ensure privilege member permission 'Write IPA Configuration' is absent
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
permission:
- "Write IPA Configuration"
action: member
state: absent
# Rename privilege "Broad Privilege" to "DNS Special Privilege"
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
rename: DNS Special Privilege
state: renamed
# Ensure privilege "DNS Special Privilege" is absent
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: DNS Special Privilege
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
gen_intersection_list
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_privilege(module, name):
"""Find if a privilege with the given name already exist."""
try:
_result = module.ipa_command("privilege_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if privilege name is not found.
return None
return _result["result"]
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
description=dict(required=False, type='str', default=None),
rename=dict(required=False, type='str', default=None,
aliases=["new_name"], ),
permission=dict(required=False, type='list', elements="str",
default=None),
action=dict(type="str", default="privilege",
choices=["member", "privilege"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent", "renamed"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
description = ansible_module.params_get("description")
permission = ansible_module.params_get("permission")
rename = ansible_module.params_get("rename")
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one privilege be added at a time.")
if action == "member":
invalid = ["description"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description", "rename"]
if action == "privilege":
invalid.append("permission")
if state == "renamed":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one privilege be added at a time.")
invalid = ["description", "permission"]
if action != "privilege":
ansible_module.fail_json(
msg="Action '%s' can not be used with state '%s'"
% (action, state))
ansible_module.params_fail_used_invalid(invalid, state, action)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
# Make sure privilege exists
res_find = find_privilege(ansible_module, name)
# Create command
if state == "present":
args = {}
if description:
args['description'] = description
if action == "privilege":
# Found the privilege
if res_find is not None:
cmp = {"description": res_find.get("description")}
if not compare_args_ipa(ansible_module, args, cmp):
commands.append([name, "privilege_mod", args])
else:
commands.append([name, "privilege_add", args])
res_find = {}
# Generate addition and removal lists
permission_add, permission_del = gen_add_del_lists(
permission, res_find.get("memberof_permission")
)
# Add members
if len(permission_add) > 0:
commands.append([name, "privilege_add_permission",
{
"permission": permission_add,
}])
# Remove members
if len(permission_del) > 0:
commands.append([
name,
"privilege_remove_permission",
{"permission": permission_del}
])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No privilege '%s'" % name)
if permission is None:
ansible_module.fail_json(msg="No permission given")
permission = gen_add_list(
permission, res_find.get("memberof_permission"))
if permission:
commands.append([name, "privilege_add_permission",
{"permission": permission}])
elif state == "absent":
if action == "privilege":
if res_find is not None:
commands.append([name, "privilege_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No privilege '%s'" % name)
if permission is None:
ansible_module.fail_json(msg="No permission given")
permission = gen_intersection_list(
permission, res_find.get("memberof_permission"))
if permission:
commands.append([name, "privilege_remove_permission",
{"permission": permission}])
elif state == "renamed":
if not rename:
ansible_module.fail_json(msg="No rename value given.")
if res_find is None:
ansible_module.fail_json(
msg="No privilege found to be renamed: '%s'" % (name))
if name != rename:
commands.append(
[name, "privilege_mod", {"rename": rename}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipapwpolicy.py 0000664 0000000 0000000 00000032666 14600563364 0023464 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
# Rafael Guterres Jeffman
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipapwpolicy
short_description: Manage FreeIPA pwpolicies
description: Manage FreeIPA pwpolicies
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The group name
type: list
elements: str
required: false
aliases: ["cn"]
maxlife:
description: Maximum password lifetime (in days). (int or "")
type: str
required: false
aliases: ["krbmaxpwdlife"]
minlife:
description: Minimum password lifetime (in hours). (int or "")
type: str
required: false
aliases: ["krbminpwdlife"]
history:
description: Password history size. (int or "")
type: str
required: false
aliases: ["krbpwdhistorylength"]
minclasses:
description: Minimum number of character classes. (int or "")
type: str
required: false
aliases: ["krbpwdmindiffchars"]
minlength:
description: Minimum length of password. (int or "")
type: str
required: false
aliases: ["krbpwdminlength"]
priority:
description: >
Priority of the policy (higher number means lower priority). (int or "")
type: str
required: false
aliases: ["cospriority"]
maxfail:
description: Consecutive failures before lockout. (int or "")
type: str
required: false
aliases: ["krbpwdmaxfailure"]
failinterval:
description: >
Period after which failure count will be reset (seconds). (int or "")
type: str
required: false
aliases: ["krbpwdfailurecountinterval"]
lockouttime:
description: Period for which lockout is enforced (seconds). (int or "")
type: str
required: false
aliases: ["krbpwdlockoutduration"]
maxrepeat:
description: >
Maximum number of same consecutive characters.
Requires IPA 4.9+. (int or "")
type: str
required: false
aliases: ["ipapwdmaxrepeat"]
maxsequence:
description: >
The maximum length of monotonic character sequences (abcd).
Requires IPA 4.9+. (int or "")
type: str
required: false
aliases: ["ipapwdmaxsequence"]
dictcheck:
description: >
Check if the password is a dictionary word.
Requires IPA 4.9+. (bool or "")
type: str
required: false
aliases: ["ipapwdictcheck"]
usercheck:
description: >
Check if the password contains the username.
Requires IPA 4.9+. (bool or "")
type: str
required: false
aliases: ["ipapwdusercheck"]
gracelimit:
description: >
Number of LDAP authentications allowed after expiration.
Requires IPA 4.10.1+. (int or "")
type: str
required: false
aliases: ["passwordgracelimit"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent"]
author:
- Thomas Woerner (@t-woerner)
- Rafael Guterres Jeffman (@rjeffman)
"""
EXAMPLES = """
# Ensure pwpolicy is set for ops
- ipapwpolicy:
ipaadmin_password: SomeADMINpassword
name: ops
minlife: 7
maxlife: 49
history: 5
priority: 1
lockouttime: 300
minlength: 8
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
def find_pwpolicy(module, name):
_args = {
"all": True,
"cn": name,
}
_result = module.ipa_command("pwpolicy_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one pwpolicy '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
return None
def gen_args(module,
maxlife, minlife, history, minclasses, minlength, priority,
maxfail, failinterval, lockouttime, maxrepeat, maxsequence,
dictcheck, usercheck, gracelimit):
_args = {}
if maxlife is not None:
_args["krbmaxpwdlife"] = maxlife
if minlife is not None:
_args["krbminpwdlife"] = minlife
if history is not None:
_args["krbpwdhistorylength"] = history
if minclasses is not None:
_args["krbpwdmindiffchars"] = minclasses
if minlength is not None:
_args["krbpwdminlength"] = minlength
if priority is not None:
_args["cospriority"] = priority
if maxfail is not None:
_args["krbpwdmaxfailure"] = maxfail
if failinterval is not None:
_args["krbpwdfailurecountinterval"] = failinterval
if lockouttime is not None:
_args["krbpwdlockoutduration"] = lockouttime
if maxrepeat is not None:
_args["ipapwdmaxrepeat"] = maxrepeat
if maxsequence is not None:
_args["ipapwdmaxsequence"] = maxsequence
if dictcheck is not None:
if module.ipa_check_version("<", "4.9.10"):
# Allowed values: "TRUE", "FALSE", ""
_args["ipapwddictcheck"] = "TRUE" if dictcheck is True else \
"FALSE" if dictcheck is False else dictcheck
else:
_args["ipapwddictcheck"] = dictcheck
if usercheck is not None:
if module.ipa_check_version("<", "4.9.10"):
# Allowed values: "TRUE", "FALSE", ""
_args["ipapwdusercheck"] = "TRUE" if usercheck is True else \
"FALSE" if usercheck is False else usercheck
else:
_args["ipapwdusercheck"] = usercheck
if gracelimit is not None:
_args["passwordgracelimit"] = gracelimit
return _args
def check_supported_params(
module, maxrepeat, maxsequence, dictcheck, usercheck, gracelimit
):
# All password checking parameters were added by the same commit,
# so we only need to test one of them.
has_password_check = module.ipa_command_param_exists(
"pwpolicy_add", "ipapwdmaxrepeat")
# check if gracelimit is supported
has_gracelimit = module.ipa_command_param_exists(
"pwpolicy_add", "passwordgracelimit")
# If needed, report unsupported password checking paramteres
if (
not has_password_check
and any([maxrepeat, maxsequence, dictcheck, usercheck])
):
module.fail_json(
msg="Your IPA version does not support arguments: "
"maxrepeat, maxsequence, dictcheck, usercheck.")
if not has_gracelimit and gracelimit is not None:
module.fail_json(
msg="Your IPA version does not support 'gracelimit'.")
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
default=None, required=False),
# present
maxlife=dict(type="str", aliases=["krbmaxpwdlife"], default=None),
minlife=dict(type="str", aliases=["krbminpwdlife"], default=None),
history=dict(type="str", aliases=["krbpwdhistorylength"],
default=None),
minclasses=dict(type="str", aliases=["krbpwdmindiffchars"],
default=None),
minlength=dict(type="str", aliases=["krbpwdminlength"],
default=None),
priority=dict(type="str", aliases=["cospriority"], default=None),
maxfail=dict(type="str", aliases=["krbpwdmaxfailure"],
default=None),
failinterval=dict(type="str",
aliases=["krbpwdfailurecountinterval"],
default=None),
lockouttime=dict(type="str", aliases=["krbpwdlockoutduration"],
default=None),
maxrepeat=dict(type="str", aliases=["ipapwdmaxrepeat"],
default=None),
maxsequence=dict(type="str", aliases=["ipapwdmaxsequence"],
default=None),
dictcheck=dict(type="str", aliases=["ipapwdictcheck"],
default=None),
usercheck=dict(type="str", aliases=["ipapwdusercheck"],
default=None),
gracelimit=dict(type="str", aliases=["passwordgracelimit"],
default=None),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
maxlife = ansible_module.params_get_with_type_cast(
"maxlife", int, allow_empty=True)
minlife = ansible_module.params_get_with_type_cast(
"minlife", int, allow_empty=True)
history = ansible_module.params_get_with_type_cast(
"history", int, allow_empty=True)
minclasses = ansible_module.params_get_with_type_cast(
"minclasses", int, allow_empty=True)
minlength = ansible_module.params_get_with_type_cast(
"minlength", int, allow_empty=True)
priority = ansible_module.params_get_with_type_cast(
"priority", int, allow_empty=True)
maxfail = ansible_module.params_get_with_type_cast(
"maxfail", int, allow_empty=True)
failinterval = ansible_module.params_get_with_type_cast(
"failinterval", int, allow_empty=True)
lockouttime = ansible_module.params_get_with_type_cast(
"lockouttime", int, allow_empty=True)
maxrepeat = ansible_module.params_get_with_type_cast(
"maxrepeat", int, allow_empty=True)
maxsequence = ansible_module.params_get_with_type_cast(
"maxsequence", int, allow_empty=True)
dictcheck = ansible_module.params_get_with_type_cast(
"dictcheck", bool, allow_empty=True)
usercheck = ansible_module.params_get_with_type_cast(
"usercheck", bool, allow_empty=True)
gracelimit = ansible_module.params_get_with_type_cast(
"gracelimit", int, allow_empty=True)
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if names is None:
names = [u"global_policy"]
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one pwpolicy can be set at a time.")
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
if "global_policy" in names:
ansible_module.fail_json(
msg="'global_policy' can not be made absent.")
invalid = ["maxlife", "minlife", "history", "minclasses",
"minlength", "priority", "maxfail", "failinterval",
"lockouttime", "maxrepeat", "maxsequence", "dictcheck",
"usercheck", "gracelimit"]
ansible_module.params_fail_used_invalid(invalid, state)
# Ensure gracelimit has proper limit.
if gracelimit:
if gracelimit < -1:
ansible_module.fail_json(
msg="'gracelimit' must be no less than -1")
# Init
changed = False
exit_args = {}
with ansible_module.ipa_connect():
check_supported_params(
ansible_module, maxrepeat, maxsequence, dictcheck, usercheck,
gracelimit
)
commands = []
for name in names:
# Try to find pwpolicy
res_find = find_pwpolicy(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(ansible_module,
maxlife, minlife, history, minclasses,
minlength, priority, maxfail, failinterval,
lockouttime, maxrepeat, maxsequence, dictcheck,
usercheck, gracelimit)
# Found the pwpolicy
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "pwpolicy_mod", args])
else:
commands.append([name, "pwpolicy_add", args])
elif state == "absent":
if res_find is not None:
commands.append([name, "pwpolicy_del", {}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/iparole.py 0000664 0000000 0000000 00000034765 14600563364 0022561 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
"""ansible-freeipa iparole module implementation."""
# Authors:
# Rafael Guterres Jeffman
# Thomas Woerner
#
# Copyright (C) 2020-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: iparole
short_description: Manage FreeIPA role
description: Manage FreeIPA role
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of role name strings.
type: list
elements: str
required: true
aliases: ["cn"]
description:
description: A description for the role.
type: str
required: false
rename:
description: Rename the role object.
type: str
required: false
aliases: ["new_name"]
privilege:
description: List of privileges
type: list
elements: str
required: false
user:
description: List of users.
type: list
elements: str
required: false
group:
description: List of groups.
type: list
elements: str
required: false
host:
description: List of hosts.
type: list
elements: str
required: false
hostgroup:
description: List of hostgroups.
type: list
elements: str
required: false
service:
description: List of services.
type: list
elements: str
required: false
action:
description: Work on role or member level.
type: str
choices: ["role", "member"]
default: role
required: false
state:
description: The state to ensure.
type: str
choices: ["present", "absent", "renamed"]
default: present
required: false
author:
- Rafael Guterres Jeffman (@rjeffman)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
- name: Ensure a role named `somerole` is present.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
- name: Ensure user `pinky` is a memmer of role `somerole`.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
user:
- pinky
action: member
- name: Ensure a role named `somerole` is absent.
iparole:
ipaadmin_password: SomeADMINpassword
name: somerole
state: absent
"""
# pylint: disable=wrong-import-position
# pylint: disable=import-error
# pylint: disable=no-name-in-module
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, gen_add_del_lists, compare_args_ipa, \
gen_intersection_list, ensure_fqdn
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_role(module, name):
"""Find if a role with the given name already exist."""
try:
_result = module.ipa_command("role_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if role name is not found.
return None
return _result["result"]
def gen_args(module):
"""Generate arguments for executing commands."""
arg_map = {
"description": "description",
"rename": "rename",
}
args = {}
for param, arg in arg_map.items():
value = module.params_get(param)
if value is not None:
args[arg] = value
return args
def check_parameters(module):
"""Check if parameters passed for module processing are valid."""
action = module.params_get("action")
state = module.params_get("state")
invalid = []
if state == "renamed":
if action == "member":
module.fail_json(
msg="Invalid action 'member' with state 'renamed'.")
invalid = [
"description",
"user", "group",
"host", "hostgroup",
"service",
"privilege",
]
if state == "present":
invalid = ["rename"]
if action == "member":
invalid.extend(['description'])
if state == "absent":
invalid.extend(['description', 'rename'])
if action != "member":
invalid.extend(['privilege'])
module.params_fail_used_invalid(invalid, state, action)
def get_member_host_with_fqdn_lowercase(module, mod_member):
"""Retrieve host members from module, as FQDN, lowercase."""
default_domain = module.ipa_get_domain()
hosts = module.params_get(mod_member)
return (
[ensure_fqdn(host, default_domain).lower() for host in hosts]
if hosts
else hosts
)
def ensure_absent_state(module, name, action, res_find):
"""Define commands to ensure absent state."""
commands = []
if action == "role":
commands.append([name, 'role_del', {}])
if action == "member":
_members = module.params_get_lowercase("privilege")
if _members is not None:
del_list = gen_intersection_list(
_members,
result_get_value_lowercase(res_find, "memberof_privilege")
)
if del_list:
commands.append([name, "role_remove_privilege",
{"privilege": del_list}])
member_args = {}
for key in ['user', 'group', 'hostgroup']:
_members = module.params_get_lowercase(key)
if _members:
del_list = gen_intersection_list(
_members,
result_get_value_lowercase(res_find, "member_%s" % key)
)
if del_list:
member_args[key] = del_list
# ensure hosts are FQDN.
_members = get_member_host_with_fqdn_lowercase(module, "host")
if _members:
del_list = gen_intersection_list(
_members, res_find.get('member_host'))
if del_list:
member_args["host"] = del_list
_services = get_service_param(module, "service")
if _services:
_existing = result_get_value_lowercase(res_find, "member_service")
items = gen_intersection_list(_services.keys(), _existing)
if items:
member_args["service"] = [_services[key] for key in items]
# Only add remove command if there's at least one member no manage.
if member_args:
commands.append([name, "role_remove_member", member_args])
return commands
def get_service_param(module, key):
"""
Retrieve dict of services, with realm, from the module parameters.
As the services are compared in a case insensitive manner, but
are recorded in a case preserving way, a dict mapping the services
in lowercase to the provided module parameter is generated, so
that dict keys can be used for comparison and the values are used
with IPA API.
"""
_services = module.params_get(key)
if _services is not None:
ipa_realm = module.ipa_get_realm()
_services = [
to_text(svc) if '@' in svc else ('%s@%s' % (svc, ipa_realm))
for svc in _services
]
if _services:
_services = {svc.lower(): svc for svc in _services}
return _services
def result_get_value_lowercase(res_find, key, default=None):
"""
Retrieve a member of a dictionary converted to lowercase.
If field data is a string it is returned in lowercase. If
field data is a list or tuple, it is assumed that all values
are strings and the result is a list of strings in lowercase.
If 'key' is not found in the dictionary, returns 'default'.
"""
existing = res_find.get(key)
if existing is not None:
if isinstance(existing, (list, tuple)):
existing = [to_text(item).lower() for item in existing]
if isinstance(existing, (str, unicode)):
existing = existing.lower()
else:
existing = default
return existing
def gen_services_add_del_lists(module, mod_member, res_find, res_member):
"""Generate add/del lists for service principals."""
add_list, del_list = None, None
_services = get_service_param(module, mod_member)
if _services is not None:
_existing = result_get_value_lowercase(res_find, res_member)
add_list, del_list = gen_add_del_lists(_services.keys(), _existing)
if add_list:
add_list = [_services[key] for key in add_list]
if del_list:
del_list = [to_text(item) for item in del_list]
return add_list, del_list
def ensure_role_with_members_is_present(module, name, res_find, action):
"""Define commands to ensure member are present for action `role`."""
commands = []
_members = module.params_get_lowercase("privilege")
if _members:
add_list, del_list = gen_add_del_lists(
_members,
result_get_value_lowercase(res_find, "memberof_privilege")
)
if add_list:
commands.append([name, "role_add_privilege",
{"privilege": add_list}])
if action == "role" and del_list:
commands.append([name, "role_remove_privilege",
{"privilege": del_list}])
add_members = {}
del_members = {}
for key in ["user", "group", "hostgroup"]:
_members = module.params_get_lowercase(key)
if _members is not None:
add_list, del_list = gen_add_del_lists(
_members,
result_get_value_lowercase(res_find, "member_%s" % key)
)
if add_list:
add_members[key] = add_list
if del_list:
del_members[key] = del_list
# ensure hosts are FQDN.
_members = get_member_host_with_fqdn_lowercase(module, "host")
if _members:
add_list, del_list = gen_add_del_lists(
_members, res_find.get('member_host'))
if add_list:
add_members["host"] = add_list
if del_list:
del_members["host"] = del_list
(add_services, del_services) = gen_services_add_del_lists(
module, "service", res_find, "member_service")
if add_services:
add_members["service"] = add_services
if del_services:
del_members["service"] = del_services
if add_members:
commands.append([name, "role_add_member", add_members])
# Only remove members if ensuring role, not acting on members.
if action == "role" and del_members:
commands.append([name, "role_remove_member", del_members])
return commands
def role_commands_for_name(module, state, action, name):
"""Define commands for the Role module."""
commands = []
res_find = find_role(module, name)
if state == "renamed":
args = gen_args(module)
if res_find is None:
module.fail_json(msg="No role '%s'" % name)
else:
commands.append([name, 'role_mod', args])
if state == "present":
args = gen_args(module)
if action == "role":
if res_find is None:
commands.append([name, 'role_add', args])
res_find = {}
else:
if not compare_args_ipa(module, args, res_find):
commands.append([name, 'role_mod', args])
if action == "member":
if res_find is None:
module.fail_json(msg="No role '%s'" % name)
cmds = ensure_role_with_members_is_present(
module, name, res_find, action
)
commands.extend(cmds)
if state == "absent" and res_find is not None:
cmds = ensure_absent_state(module, name, action, res_find)
commands.extend(cmds)
return commands
def create_module():
"""Create module description."""
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# generalgroups
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
description=dict(required=False, type="str", default=None),
rename=dict(required=False, type="str", default=None,
aliases=["new_name"]),
# members
privilege=dict(required=False, type='list', elements="str",
default=None),
user=dict(required=False, type='list', elements="str",
default=None),
group=dict(required=False, type='list', elements="str",
default=None),
host=dict(required=False, type='list', elements="str",
default=None),
hostgroup=dict(required=False, type='list', elements="str",
default=None),
service=dict(required=False, type='list', elements="str",
default=None),
# state
action=dict(type="str", default="role",
choices=["role", "member"]),
state=dict(type="str", default="present",
choices=["present", "absent", "renamed"]),
),
supports_check_mode=True,
mutually_exclusive=[],
required_one_of=[]
)
ansible_module._ansible_debug = True # pylint: disable=protected-access
return ansible_module
def main():
"""Process role module script."""
ansible_module = create_module()
check_parameters(ansible_module)
# Init
# Connect to IPA API
with ansible_module.ipa_connect():
state = ansible_module.params_get("state")
action = ansible_module.params_get("action")
names = ansible_module.params_get("name")
commands = []
for name in names:
cmds = role_commands_for_name(ansible_module, state, action, name)
commands.extend(cmds)
exit_args = {}
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaselfservice.py 0000664 0000000 0000000 00000022331 14600563364 0024114 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2020-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaselfservice
short_description: Manage FreeIPA selfservices
description: Manage FreeIPA selfservices and selfservice attributes
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of selfservice name strings.
type: list
elements: str
required: true
aliases: ["aciname"]
permission:
description: Permissions to grant (read, write). Default is write.
type: list
elements: str
required: false
aliases: ["permissions"]
attribute:
description: Attribute list to which the selfservice applies
type: list
elements: str
required: false
aliases: ["attrs"]
action:
description: Work on selfservice or member level.
type: str
choices: ["selfservice", "member"]
default: selfservice
required: false
state:
description: The state to ensure.
type: str
choices: ["present", "absent"]
default: present
required: false
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure selfservice "Users can manage their own name details" is present
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
permission: read
attribute:
- title
- initials
# Ensure selfservice "Users can manage their own name details" member
# attribute departmentnumber is present
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
attribute:
- initials
action: member
# Ensure selfservice "Users can manage their own name details" member
# attributes employeetype and employeenumber are present
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
attribute:
- title
- initials
action: member
state: absent
# Ensure selfservice "Users can manage their own name details" is absent
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
def find_selfservice(module, name):
"""Find if a selfservice with the given name already exist."""
try:
_result = module.ipa_command("selfservice_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if selfservice name is not found.
return None
return _result["result"]
def gen_args(permission, attribute):
_args = {}
if permission is not None:
_args["permissions"] = permission
if attribute is not None:
_args["attrs"] = attribute
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["aciname"],
required=True),
# present
permission=dict(required=False, type='list', elements="str",
aliases=["permissions"], default=None),
attribute=dict(required=False, type='list', elements="str",
aliases=["attrs"], default=None),
action=dict(type="str", default="selfservice",
choices=["member", "selfservice"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
permission = ansible_module.params_get("permission")
attribute = ansible_module.params_get("attribute")
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one selfservice be added at a time.")
if action == "member":
invalid = ["permission"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["permission"]
if action == "selfservice":
invalid.append("attribute")
ansible_module.params_fail_used_invalid(invalid, state, action)
if permission is not None:
perm = [p for p in permission if p not in ("read", "write")]
if perm:
ansible_module.fail_json(msg="Invalid permission '%s'" % perm)
if len(set(permission)) != len(permission):
ansible_module.fail_json(
msg="Invalid permission '%s', items are not unique" %
repr(permission))
if attribute is not None:
if len(set(attribute)) != len(attribute):
ansible_module.fail_json(
msg="Invalid attribute '%s', items are not unique" %
repr(attribute))
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
# Make sure selfservice exists
res_find = find_selfservice(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(permission, attribute)
if action == "selfservice":
# Found the selfservice
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "selfservice_mod", args])
else:
commands.append([name, "selfservice_add", args])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No selfservice '%s'" % name)
if attribute is None:
ansible_module.fail_json(msg="No attributes given")
# New attribute list (add given ones to find result)
# Make list with unique entries
attrs = list(set(list(res_find["attrs"]) + attribute))
if len(attrs) > len(res_find["attrs"]):
commands.append([name, "selfservice_mod",
{"attrs": attrs}])
elif state == "absent":
if action == "selfservice":
if res_find is not None:
commands.append([name, "selfservice_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No selfservice '%s'" % name)
if attribute is None:
ansible_module.fail_json(msg="No attributes given")
# New attribute list (remove given ones from find result)
# Make list with unique entries
attrs = list(set(res_find["attrs"]) - set(attribute))
if len(attrs) < 1:
ansible_module.fail_json(
msg="At minimum one attribute is needed.")
# Entries New number of attributes is smaller
if len(attrs) < len(res_find["attrs"]):
commands.append([name, "selfservice_mod",
{"attrs": attrs}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaserver.py 0000664 0000000 0000000 00000032217 14600563364 0023114 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2021-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaserver
short_description: Manage FreeIPA server
description: Manage FreeIPA server
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of server name strings.
type: list
elements: str
required: true
aliases: ["cn"]
location:
description: |
The server DNS location.
Only available with 'state: present'.
Use "" for location reset.
type: str
required: false
aliases: ["ipalocation_location"]
service_weight:
description: |
Weight for server services
Values 0 to 65535, -1 for weight reset.
Only available with 'state: present'.
required: false
type: int
aliases: ["ipaserviceweight"]
hidden:
description: |
Set hidden state of a server.
Only available with 'state: present'.
required: false
type: bool
no_members:
description: |
Suppress processing of membership attributes
Only available with 'state: present'.
required: false
type: bool
delete_continue:
description: |
Continuous mode: Don't stop on errors.
Only available with 'state: absent'.
required: false
type: bool
aliases: ["continue"]
ignore_last_of_role:
description: |
Skip a check whether the last CA master or DNS server is removed.
Only available with 'state: absent'.
required: false
type: bool
ignore_topology_disconnect:
description: |
Ignore topology connectivity problems after removal.
Only available with 'state: absent'.
required: false
type: bool
force:
description: |
Force server removal even if it does not exist.
Will always result in changed.
Only available with 'state: absent'.
required: false
type: bool
state:
description: The state to ensure.
type: str
choices: ["present", "absent"]
default: present
required: false
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure server server.example.com is already present in the topology
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
# Ensure server server.example.com is absent from the topology
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
state: absent
# Ensure server server.example.com has location mylocation
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
location: mylocation
# Ensure server server.example.com does not have a location
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
location: ""
# Ensure server server.example.com has service weight 1
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
service_weight: 1
# Ensure server server.example.com does not have a service weight
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
service_weight: -1
# Ensure server server.example.com is hidden
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
hidden: yes
# Ensure server server.example.com is not hidden
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
hidden: no
# Ensure server server.example.com is absent from the topology in continuous
# mode to ignore errors
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
continue: yes
state: absent
# Ensure server "server.example.com" is absent from the topology with skipping
# the last of role check
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
ignore_last_of_role: yes
state: absent
# Ensure server server "server.example.com" is absent from the topology with
# skipping the topology disconnect check
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
ignore_topology_disconnect: yes
state: absent
# Ensure server server.example.com is absent in force mode
- ipaserver:
ipaadmin_password: SomeADMINpassword
name: server.example.com
force: yes
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, DNSName
def find_server(module, name):
"""Find if a server with the given name already exist."""
try:
_result = module.ipa_command("server_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if server name is not found.
return None
return _result["result"]
def server_role_status(module, name):
"""Get server role of a hidden server with the given name."""
try:
_result = module.ipa_command_no_name("server_role_find",
{"server_server": name,
"role_servrole": 'IPA master',
"include_master": True,
"raw": True,
"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if server name is not found.
return None
return _result["result"][0]
def gen_args(location, service_weight, no_members, delete_continue,
ignore_topology_disconnect, ignore_last_of_role, force):
_args = {}
if location is not None:
if location != "":
_args["ipalocation_location"] = DNSName(location)
else:
_args["ipalocation_location"] = None
if service_weight is not None:
_args["ipaserviceweight"] = service_weight
if no_members is not None:
_args["no_members"] = no_members
if delete_continue is not None:
_args["continue"] = delete_continue
if ignore_topology_disconnect is not None:
_args["ignore_topology_disconnect"] = ignore_topology_disconnect
if ignore_last_of_role is not None:
_args["ignore_last_of_role"] = ignore_last_of_role
if force is not None:
_args["force"] = force
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
location=dict(required=False, type='str',
aliases=["ipalocation_location"], default=None),
service_weight=dict(required=False, type='int',
aliases=["ipaserviceweight"], default=None),
hidden=dict(required=False, type='bool', default=None),
no_members=dict(required=False, type='bool', default=None),
# absent
delete_continue=dict(required=False, type='bool',
aliases=["continue"], default=None),
ignore_topology_disconnect=dict(required=False, type='bool',
default=None),
ignore_last_of_role=dict(required=False, type='bool',
default=None),
force=dict(required=False, type='bool',
default=None),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
location = ansible_module.params_get("location")
service_weight = ansible_module.params_get("service_weight")
# Service weight smaller than 0 leads to resetting service weight
if service_weight is not None and \
(service_weight < -1 or service_weight > 65535):
ansible_module.fail_json(
msg="service_weight %d is out of range [-1 .. 65535]" %
service_weight)
if service_weight == -1:
service_weight = ""
hidden = ansible_module.params_get("hidden")
no_members = ansible_module.params_get("no_members")
# absent
delete_continue = ansible_module.params_get("delete_continue")
ignore_topology_disconnect = ansible_module.params_get(
"ignore_topology_disconnect")
ignore_last_of_role = ansible_module.params_get("ignore_last_of_role")
force = ansible_module.params_get("force")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one server can be ensured at a time.")
invalid = ["delete_continue", "ignore_topology_disconnect",
"ignore_last_of_role", "force"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["location", "service_weight", "hidden", "no_members"]
ansible_module.params_fail_used_invalid(invalid, state)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
# Make sure server exists
res_find = find_server(ansible_module, name)
# Generate args
args = gen_args(location, service_weight, no_members,
delete_continue, ignore_topology_disconnect,
ignore_last_of_role, force)
# Create command
if state == "present":
# Server not found
if res_find is None:
ansible_module.fail_json(
msg="Server '%s' not found" % name)
# Remove location from args if "" (transformed to None)
# and "ipalocation_location" not in res_find for idempotency
if "ipalocation_location" in args and \
args["ipalocation_location"] is None and \
"ipalocation_location" not in res_find:
del args["ipalocation_location"]
# Remove service weight from args if ""
# and "ipaserviceweight" not in res_find for idempotency
if "ipaserviceweight" in args and \
args["ipaserviceweight"] == "" and \
"ipaserviceweight" not in res_find:
del args["ipaserviceweight"]
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args, res_find):
commands.append([name, "server_mod", args])
# hidden handling
if hidden is not None:
res_role_status = server_role_status(ansible_module,
name)
if "status" in res_role_status:
# Fail if status is configured, it should be done
# only in the installer
if res_role_status["status"] == "configured":
ansible_module.fail_json(
msg="'%s' in configured state, "
"unable to change state" % state)
if hidden and res_role_status["status"] == "enabled":
commands.append([name, "server_state",
{"state": "hidden"}])
if not hidden and \
res_role_status["status"] == "hidden":
commands.append([name, "server_state",
{"state": "enabled"}])
elif state == "absent":
if res_find is not None or force:
commands.append([name, "server_del", args])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaservice.py 0000664 0000000 0000000 00000104646 14600563364 0023254 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Denis Karpelevich
# Rafael Guterres Jeffman
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaservice
short_description: Manage FreeIPA service
description: Manage FreeIPA service
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The service to manage
type: list
elements: str
required: true
aliases: ["service"]
services:
description: The list of service dicts.
type: list
elements: dict
suboptions:
name:
description: The service to manage
type: str
required: true
aliases: ["service"]
certificate:
description: Base-64 encoded service certificate.
required: false
type: list
elements: str
aliases: ["usercertificate"]
pac_type:
description: Supported PAC type.
required: false
choices: ["MS-PAC", "PAD", "NONE", ""]
type: list
elements: str
aliases: ["pac_type", "ipakrbauthzdata"]
auth_ind:
description: Defines an allow list for Authentication Indicators.
type: list
elements: str
required: false
choices: ["otp", "radius", "pkinit", "hardened", "idp", ""]
aliases: ["krbprincipalauthind"]
skip_host_check:
description: Skip checking if host object exists.
required: False
type: bool
force:
description: Force principal name even if host is not in DNS.
required: False
type: bool
requires_pre_auth:
description: Pre-authentication is required for the service.
required: false
type: bool
aliases: ["ipakrbrequirespreauth"]
ok_as_delegate:
description: Client credentials may be delegated to the service.
required: false
type: bool
aliases: ["ipakrbokasdelegate"]
ok_to_auth_as_delegate:
description: Allow service to authenticate on behalf of a client.
required: false
type: bool
aliases: ["ipakrboktoauthasdelegate"]
principal:
description: List of principal aliases for the service.
required: false
type: list
elements: str
aliases: ["krbprincipalname"]
smb:
description: Add a SMB service.
required: false
type: bool
netbiosname:
description: NETBIOS name for the SMB service.
required: false
type: str
host:
description: Host that can manage the service.
required: false
type: list
elements: str
aliases: ["managedby_host"]
allow_create_keytab_user:
description: Users allowed to create a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_user"]
allow_create_keytab_group:
description: Groups allowed to create a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_group"]
allow_create_keytab_host:
description: Hosts allowed to create a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_host"]
allow_create_keytab_hostgroup:
description: Host group allowed to create a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_hostgroup"]
allow_retrieve_keytab_user:
description: User allowed to retrieve a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_user"]
allow_retrieve_keytab_group:
description: Groups allowed to retrieve a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_group"]
allow_retrieve_keytab_host:
description: Hosts allowed to retrieve a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_host"]
allow_retrieve_keytab_hostgroup:
description: Host groups allowed to retrieve a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_hostgroup"]
certificate:
description: Base-64 encoded service certificate.
required: false
type: list
elements: str
aliases: ["usercertificate"]
pac_type:
description: Supported PAC type.
required: false
choices: ["MS-PAC", "PAD", "NONE", ""]
type: list
elements: str
aliases: ["pac_type", "ipakrbauthzdata"]
auth_ind:
description: Defines an allow list for Authentication Indicators.
type: list
elements: str
required: false
choices: ["otp", "radius", "pkinit", "hardened", "idp", ""]
aliases: ["krbprincipalauthind"]
skip_host_check:
description: Skip checking if host object exists.
required: False
type: bool
force:
description: Force principal name even if host is not in DNS.
required: False
type: bool
requires_pre_auth:
description: Pre-authentication is required for the service.
required: false
type: bool
aliases: ["ipakrbrequirespreauth"]
ok_as_delegate:
description: Client credentials may be delegated to the service.
required: false
type: bool
aliases: ["ipakrbokasdelegate"]
ok_to_auth_as_delegate:
description: Allow service to authenticate on behalf of a client.
required: false
type: bool
aliases: ["ipakrboktoauthasdelegate"]
principal:
description: List of principal aliases for the service.
required: false
type: list
elements: str
aliases: ["krbprincipalname"]
smb:
description: Add a SMB service.
required: false
type: bool
netbiosname:
description: NETBIOS name for the SMB service.
required: false
type: str
host:
description: Host that can manage the service.
required: false
type: list
elements: str
aliases: ["managedby_host"]
allow_create_keytab_user:
description: Users allowed to create a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_user"]
allow_create_keytab_group:
description: Groups allowed to create a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_group"]
allow_create_keytab_host:
description: Hosts allowed to create a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_host"]
allow_create_keytab_hostgroup:
description: Host group allowed to create a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_write_keys_hostgroup"]
allow_retrieve_keytab_user:
description: User allowed to retrieve a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_user"]
allow_retrieve_keytab_group:
description: Groups allowed to retrieve a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_group"]
allow_retrieve_keytab_host:
description: Hosts allowed to retrieve a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_host"]
allow_retrieve_keytab_hostgroup:
description: Host groups allowed to retrieve a keytab of this host.
required: false
type: list
elements: str
aliases: ["ipaallowedtoperform_read_keys_hostgroup"]
delete_continue:
description:
Continuous mode. Don't stop on errors. Valid only if `state` is `absent`.
required: false
type: bool
aliases: ["continue"]
action:
description: Work on service or member level
type: str
default: service
choices: ["member", "service"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent", "disabled"]
author:
- Rafael Guterres Jeffman (@rjeffman)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure service is present
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
pac_type:
- MS-PAC
- PAD
auth_ind: otp
skip_host_check: true
force: false
requires_pre_auth: true
ok_as_delegate: false
ok_to_auth_as_delegate: false
# Ensure service is absent
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
state: absent
# Ensure service member certificate is present.
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
certificate:
- >
MIIC/zCCAeegAwIBAgIUMNHIbn+hhrOVew/2WbkteisV29QwDQYJKoZIhvcNAQELBQAw
DzENMAsGA1UEAwwEdGVzdDAeFw0yMDAyMDQxNDQxMDhaFw0zMDAyMDExNDQxMDhaMA8x
DTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+XVVG
FYpHVkcDfVnNInE1Y/pFciegdzqTjMwUWlRL4Zt3u96GhaMLRbtk+OfEkzLUAhWBOwEr
aELJzMLJOMvjYF3C+TiGO7dStFLikZmccuSsSIXjnzIPwBXa8KvgRVRyGLoVvGbLJvmj
fMXp0nIToTx/i74KF9S++WEes9H5ErJ99CDhLKFgq0amnvsgparYXhypHaRLnikn0vQI
Nt55YoEd1s4KrvEcD2VdZkIMPbLRu2zFvMprF3cjQQG4LT9ggfEXNIPZ1nQWAnAsu7OJ
EkNF+E4Mkmpcxj9aGUVt5bsq1D+Tzj3GsidSX0nSNcZ2JltXRnL/5v63g5cZyE+nAgMB
AAGjUzBRMB0GA1UdDgQWBBRV0j7JYukuH/r/t9+QeNlRLXDlEDAfBgNVHSMEGDAWgBRV
0j7JYukuH/r/t9+QeNlRLXDlEDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA
A4IBAQCgVy1+1kNwHs5y1Zp0WjMWGCJC6/zw7FDG4OW5r2GJiCXZYdJ0UonY9ZtoVLJP
rp2/DAv1m5DtnDhBYqicuPgLzEkOS1KdTi20Otm/J4yxLLrZC5W4x0XOeSVPXOJuQWfw
Q5pPvKkn6WxYUYkGwIt1OH2nSMngkbami3CbSmKZOCpgQIiSlQeDJ8oGjWFMLDymYSHo
VOIXHwNoooyEiaio3693l6noobyGv49zyCVLVR1DC7i6RJ186ql0av+D4vPoiF5mX7+s
KC2E8xEj9uKQ5GTWRh59VnRBVC/SiMJ/H78tJnBAvoBwXxSEvj8Z3Kjm/BQqZfv4IBsA
5yqV7MVq
action: member
state: present
# Ensure principal host/test.example.com present in service.
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
principal:
- host/test.example.com
action: member
# Ensure host can manage service.
- ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com
host:
- host1.example.com
- host2.example.com
action: member
# Ensure multiple services are present.
- ipaservice:
ipaadmin_password: SomeADMINpassword
services:
- name: HTTP/www.example.com
host:
- host1.example.com
- name: HTTP/www.service.com
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, encode_certificate, \
gen_add_del_lists, gen_add_list, gen_intersection_list, ipalib_errors, \
api_get_realm, to_text
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_service(module, name):
_args = {
"all": True,
}
try:
_result = module.ipa_command("service_show", name, _args)
except ipalib_errors.NotFound:
return None
if "result" in _result:
_res = _result["result"]
certs = _res.get("usercertificate")
if certs is not None:
_res["usercertificate"] = [encode_certificate(cert) for
cert in certs]
return _res
return None
def gen_args(pac_type, auth_ind, skip_host_check, force, requires_pre_auth,
ok_as_delegate, ok_to_auth_as_delegate):
_args = {}
if pac_type is not None:
_args['ipakrbauthzdata'] = pac_type
if auth_ind is not None:
_args['krbprincipalauthind'] = auth_ind
if skip_host_check is not None:
_args['skip_host_check'] = skip_host_check
if force is not None:
_args['force'] = force
if requires_pre_auth is not None:
_args['ipakrbrequirespreauth'] = requires_pre_auth
if ok_as_delegate is not None:
_args['ipakrbokasdelegate'] = ok_as_delegate
if ok_to_auth_as_delegate is not None:
_args['ipakrboktoauthasdelegate'] = ok_to_auth_as_delegate
return _args
def gen_args_smb(netbiosname, ok_as_delegate, ok_to_auth_as_delegate):
_args = {}
if netbiosname is not None:
_args['ipantflatname'] = netbiosname
if ok_as_delegate is not None:
_args['ipakrbokasdelegate'] = ok_as_delegate
if ok_to_auth_as_delegate is not None:
_args['ipakrboktoauthasdelegate'] = ok_to_auth_as_delegate
return _args
def check_parameters(module, state, action, names):
# invalid parameters for everything but state 'present', action 'service'.
invalid = ['pac_type', 'auth_ind', 'skip_host_check',
'force', 'requires_pre_auth', 'ok_as_delegate',
'ok_to_auth_as_delegate', 'smb', 'netbiosname']
# invalid parameters when not handling service members.
invalid_not_member = \
['principal', 'certificate', 'host', 'allow_create_keytab_user',
'allow_create_keytab_group', 'allow_create_keytab_host',
'allow_create_keytab_hostgroup', 'allow_retrieve_keytab_user',
'allow_retrieve_keytab_group', 'allow_retrieve_keytab_host',
'allow_retrieve_keytab_hostgroup']
if state == 'present':
if names is not None and len(names) != 1:
module.fail_json(msg="Only one service can be added at a time "
"using 'name'.")
if action == 'service':
invalid = ['delete_continue']
if (
not module.params_get('smb')
and module.params_get('netbiosname')
):
module.fail_json(
msg="Argument 'netbiosname' can not be used without "
"SMB service.")
else:
invalid.append('delete_continue')
elif state == 'absent':
if action == "service":
invalid.extend(invalid_not_member)
else:
invalid.extend('delete_continue')
elif state == 'disabled':
invalid.extend(invalid_not_member)
invalid.append('delete_continue')
if action != "service":
module.fail_json(
msg="Invalid action '%s' for state '%s'" % (action, state))
else:
module.fail_json(msg="Invalid state '%s'" % (state))
module.params_fail_used_invalid(invalid, state, action)
def check_authind(module, auth_ind):
_invalid = module.ipa_command_invalid_param_choices(
"service_add", "krbprincipalauthind", auth_ind)
if _invalid:
module.fail_json(
msg="The use of krbprincipalauthind '%s' is not supported "
"by your IPA version" % "','".join(_invalid))
def init_ansible_module():
service_spec = dict(
# service attributesstr
certificate=dict(type="list", elements="str",
aliases=['usercertificate'],
default=None, required=False),
principal=dict(type="list", elements="str",
aliases=["krbprincipalname"], default=None),
smb=dict(type="bool", required=False),
netbiosname=dict(type="str", required=False),
pac_type=dict(type="list", elements="str",
aliases=["ipakrbauthzdata"],
choices=["MS-PAC", "PAD", "NONE", ""]),
auth_ind=dict(type="list", elements="str",
aliases=["krbprincipalauthind"],
choices=["otp", "radius", "pkinit", "hardened", "idp",
""]),
skip_host_check=dict(type="bool"),
force=dict(type="bool"),
requires_pre_auth=dict(
type="bool", aliases=["ipakrbrequirespreauth"]),
ok_as_delegate=dict(type="bool", aliases=["ipakrbokasdelegate"]),
ok_to_auth_as_delegate=dict(type="bool",
aliases=["ipakrboktoauthasdelegate"]),
host=dict(type="list", elements="str", aliases=["managedby_host"],
required=False),
allow_create_keytab_user=dict(
type="list", elements="str", required=False, no_log=False,
aliases=['ipaallowedtoperform_write_keys_user']),
allow_retrieve_keytab_user=dict(
type="list", elements="str", required=False, no_log=False,
aliases=['ipaallowedtoperform_read_keys_user']),
allow_create_keytab_group=dict(
type="list", elements="str", required=False, no_log=False,
aliases=['ipaallowedtoperform_write_keys_group']),
allow_retrieve_keytab_group=dict(
type="list", elements="str", required=False, no_log=False,
aliases=['ipaallowedtoperform_read_keys_group']),
allow_create_keytab_host=dict(
type="list", elements="str", required=False, no_log=False,
aliases=['ipaallowedtoperform_write_keys_host']),
allow_retrieve_keytab_host=dict(
type="list", elements="str", required=False, no_log=False,
aliases=['ipaallowedtoperform_read_keys_host']),
allow_create_keytab_hostgroup=dict(
type="list", elements="str", required=False, no_log=False,
aliases=['ipaallowedtoperform_write_keys_hostgroup']),
allow_retrieve_keytab_hostgroup=dict(
type="list", elements="str", required=False, no_log=False,
aliases=['ipaallowedtoperform_read_keys_hostgroup']),
delete_continue=dict(type="bool", required=False,
aliases=['continue']),
)
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["service"],
default=None, required=False),
services=dict(type="list",
default=None,
options=dict(
# Here name is a simple string
name=dict(type="str", required=True,
aliases=["service"]),
# Add service specific parameters
**service_spec
),
elements='dict',
required=False),
# action
action=dict(type="str", default="service",
choices=["member", "service"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent", "disabled"]),
# Add service specific parameters for simple use case
**service_spec
),
mutually_exclusive=[["name", "services"]],
required_one_of=[["name", "services"]],
supports_check_mode=True,
)
ansible_module._ansible_debug = True
return ansible_module
def main():
ansible_module = init_ansible_module()
# Get parameters
# general
names = ansible_module.params_get("name")
services = ansible_module.params_get("services")
# service attributes
principal = ansible_module.params_get("principal")
certificate = ansible_module.params_get("certificate")
# Any leading or trailing whitespace is removed while adding the
# certificate with serive_add_cert. To be able to compare the results
# from service_show with the given certificates we have to remove the
# white space also.
if certificate is not None:
certificate = [cert.strip() for cert in certificate]
pac_type = ansible_module.params_get(
"pac_type", allow_empty_list_item=True)
auth_ind = ansible_module.params_get(
"auth_ind", allow_empty_list_item=True)
skip_host_check = ansible_module.params_get("skip_host_check")
force = ansible_module.params_get("force")
requires_pre_auth = ansible_module.params_get("requires_pre_auth")
ok_as_delegate = ansible_module.params_get("ok_as_delegate")
ok_to_auth_as_delegate = ansible_module.params_get(
"ok_to_auth_as_delegate")
smb = ansible_module.params_get("smb")
netbiosname = ansible_module.params_get("netbiosname")
host = ansible_module.params_get("host")
delete_continue = ansible_module.params_get("delete_continue")
# action
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# check parameters
if (names is None or len(names) < 1) and \
(services is None or len(services) < 1):
ansible_module.fail_json(msg="At least one name or services is "
"required")
check_parameters(ansible_module, state, action, names)
# Use services if names is None
if services is not None:
names = services
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
has_skip_host_check = ansible_module.ipa_command_param_exists(
"service_add", "skip_host_check")
if skip_host_check and not has_skip_host_check:
ansible_module.fail_json(
msg="Skipping host check is not supported by your IPA version")
check_authind(ansible_module, auth_ind)
commands = []
keytab_members = ["user", "group", "host", "hostgroup"]
service_set = set()
for service in names:
if isinstance(service, dict):
name = service.get("name")
if name in service_set:
ansible_module.fail_json(
msg="service '%s' is used more than once" % name)
service_set.add(name)
principal = service.get("principal")
certificate = service.get("certificate")
# Any leading or trailing whitespace is removed while adding
# the certificate with serive_add_cert. To be able to compare
# the results from service_show with the given certificates
# we have to remove the white space also.
if certificate is not None:
certificate = [cert.strip() for cert in certificate]
pac_type = service.get("pac_type")
auth_ind = service.get("auth_ind")
check_authind(ansible_module, auth_ind)
skip_host_check = service.get("skip_host_check")
if skip_host_check and not has_skip_host_check:
ansible_module.fail_json(
msg="Skipping host check is not supported by your IPA "
"version")
force = service.get("force")
requires_pre_auth = service.get("requires_pre_auth")
ok_as_delegate = service.get("ok_as_delegate")
ok_to_auth_as_delegate = service.get("ok_to_auth_as_delegate")
smb = service.get("smb")
netbiosname = service.get("netbiosname")
host = service.get("host")
delete_continue = service.get("delete_continue")
elif isinstance(service, (str, unicode)):
name = service
else:
ansible_module.fail_json(msg="Service '%s' is not valid" %
repr(service))
res_find = find_service(ansible_module, name)
res_principals = []
keytab = {
"retrieve": {
"allow": {k: [] for k in keytab_members},
"disallow": {k: [] for k in keytab_members},
},
"create": {
"allow": {k: [] for k in keytab_members},
"disallow": {k: [] for k in keytab_members},
},
}
certificate_add, certificate_del = [], []
host_add, host_del = [], []
principal_add, principal_del = [], []
if principal and res_find:
# When comparing principals to the existing ones,
# the REALM is needded, and are added here for those
# that do not have it.
principal = [
p if "@" in p
else "%s@%s" % (p, api_get_realm())
for p in principal
]
principal = list(set(principal))
# Create list of existing principal aliases as strings
# to compare with provided ones.
canonicalname = {
to_text(p)
for p in res_find.get("krbcanonicalname", [])
}
res_principals = [
to_text(elem)
for elem in res_find.get("krbprincipalname", [])
]
res_principals = list(set(res_principals) - canonicalname)
if state == "present":
if action == "service":
args = gen_args(
pac_type, auth_ind, skip_host_check, force,
requires_pre_auth, ok_as_delegate,
ok_to_auth_as_delegate)
if not has_skip_host_check and 'skip_host_check' in args:
del args['skip_host_check']
if smb:
if res_find is None:
_name = "cifs/" + name
res_find = find_service(ansible_module, _name)
if res_find is None:
_args = gen_args_smb(
netbiosname, ok_as_delegate,
ok_to_auth_as_delegate)
commands.append(
[name, 'service_add_smb', _args])
res_find = {}
# service_add_smb will prefix 'name' with
# "cifs/", so we will need to change it here,
# so that service_mod, if called later, works.
name = _name
if res_find is None:
commands.append([name, 'service_add', args])
# Use an empty res_find to manage members
res_find = {}
else:
for remove in ['skip_host_check', 'force']:
if remove in args:
del args[remove]
if (
"ipakrbauthzdata" in args
and (
args.get("ipakrbauthzdata", [""]) ==
res_find.get("ipakrbauthzdata", [""])
)
):
del args["ipakrbauthzdata"]
if (
"krbprincipalauthind" in args
and (
args.get("krbprincipalauthind", [""]) ==
res_find.get("krbprincipalauthind", [""])
)
):
del args["krbprincipalauthind"]
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "service_mod", args])
# Manage members
certificate_add, certificate_del = gen_add_del_lists(
certificate, res_find.get("usercertificate"))
host_add, host_del = gen_add_del_lists(
host, res_find.get('managedby_host'))
principal_add, principal_del = gen_add_del_lists(
principal, res_principals)
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No service '%s'" % name)
certificate_add = gen_add_list(
certificate, res_find.get("usercertificate"))
host_add = gen_add_list(
host, res_find.get('managedby_host'))
principal_add = gen_add_list(principal, res_principals)
# get keytab management lists for any 'action'.
for perm in ["create", "retrieve"]:
oper = "write" if perm == "create" else "read"
for key in ["user", "group", "host", "hostgroup"]:
add_list, del_list = (
gen_add_del_lists(
ansible_module.params_get(
"allow_%s_keytab_%s" % (perm, key)
),
res_find.get(
'ipaallowedtoperform_%s_keys_%s'
% (oper, key)
)
)
)
keytab[perm]["allow"][key] = add_list
# Only remove members if action is 'service'
if action == "service":
keytab[perm]["disallow"][key] = del_list
elif state == "absent":
if action == "service":
if res_find is not None:
args = {'continue': delete_continue}
commands.append([name, 'service_del', args])
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No service '%s'" % name)
principal_del = gen_intersection_list(
principal, res_principals)
certificate_del = gen_intersection_list(
certificate, res_find.get("usercertificate"))
host_del = gen_intersection_list(
host, res_find.get("managedby_host"))
for perm in ["create", "retrieve"]:
oper = "write" if perm == "create" else "read"
for key in ["user", "group", "host", "hostgroup"]:
res_param = (
'ipaallowedtoperform_%s_keys_%s'
% (oper, key)
)
module_params = ansible_module.params_get(
"allow_%s_keytab_%s" % (perm, key)
)
existing = res_find.get(res_param)
del_list = (
gen_intersection_list(module_params, existing)
)
keytab[perm]["disallow"][key] = del_list
elif state == "disabled":
if action == "service":
if res_find is not None:
has_cert = bool(res_find.get('usercertificate'))
has_keytab = res_find.get('has_keytab', False)
if has_cert or has_keytab:
commands.append([name, 'service_disable', {}])
else:
ansible_module.fail_json(
msg="Invalid action '%s' for state '%s'" %
(action, state))
# Members are not managed when disabling service.
# Continue with next 'name'.
continue
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Manage members
if principal_add:
commands.append([name, "service_add_principal",
{"krbprincipalname": principal_add}])
if principal_del:
commands.append([name, "service_remove_principal",
{"krbprincipalname": principal_del}])
if certificate_add:
commands.append([name, "service_add_cert",
{"usercertificate": certificate_add}])
if certificate_del:
commands.append([name, "service_remove_cert",
{"usercertificate": certificate_del}])
if host_add:
commands.append([name, "service_add_host",
{"host": host_add}])
if host_del:
commands.append([name, "service_remove_host",
{"host": host_del}])
# manage keytab permissions.
for perm in ["create", "retrieve"]:
for mode in ["allow", "disallow"]:
for key in ["user", "group", "host", "hostgroup"]:
if keytab[perm][mode][key]:
commands.append([
name,
"service_%s_%s_keytab" % (mode, perm),
keytab[perm][mode]
])
break
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaservicedelegationrule.py 0000664 0000000 0000000 00000027747 14600563364 0026206 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaservicedelegationrule
short_description: Manage FreeIPA servicedelegationrule
description: |
Manage FreeIPA servicedelegationrule and servicedelegationrule members
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of servicedelegationrule name strings.
type: list
elements: str
required: true
aliases: ["cn"]
principal:
description: |
The list of principals. A principal can be of the format:
fqdn, fqdn@REALM, service/fqdn, service/fqdn@REALM, host/fqdn,
host/fqdn@REALM, alias$, alias$@REALM, where fqdn and fqdn@REALM
are host principals and the same as host/fqdn and host/fqd
Host princpals are only usable with IPA versions 4.9.0 and up.
type: list
elements: str
required: false
target:
description: |
The list of service delegation targets.
type: list
elements: str
required: false
aliases: ["servicedelegationtarget"]
action:
description: Work on servicedelegationrule or member level.
type: str
choices: ["servicedelegationrule", "member"]
default: servicedelegationrule
required: false
state:
description: The state to ensure.
type: str
choices: ["present", "absent"]
default: present
required: false
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure servicedelegationrule delegation-rule is present
- ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: delegation-rule
# Ensure servicedelegationrule delegation-rule member principal
# test/example.com is present
- ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: delegation-rule
principal: test/example.com
action: member
# Ensure servicedelegationrule delegation-rule member principal
# test/example.com is absent
- ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: delegation-rule
principal: test/example.com
action: member
state: absent
# Ensure servicedelegationrule delegation-rule member target
# test/example.com is present
- ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: delegation-rule
target: delegation-target
action: member
# Ensure servicedelegationrule delegation-rule member target
# test/example.com is absent
- ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: delegation-rule
target: delegation-target
action: member
state: absent
# Ensure servicedelegationrule delegation-rule is absent
- ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
name: delegation-rule
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, gen_add_del_lists, gen_add_list, gen_intersection_list, \
servicedelegation_normalize_principals, ipalib_errors
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_servicedelegationrule(module, name):
"""Find if a servicedelegationrule with the given name already exist."""
try:
_result = module.ipa_command("servicedelegationrule_show", name,
{"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if servicedelegationrule name is not found.
return None
return _result["result"]
def check_targets(module, targets):
def _check_exists(module, _type, name):
# Check if item of type _type exists using the show command
try:
module.ipa_command("%s_show" % _type, name, {})
except ipalib_errors.NotFound as e:
msg = str(e)
if "%s not found" % _type in msg:
return False
module.fail_json(msg="%s_show failed: %s" % (_type, msg))
return True
for _target in targets:
if not _check_exists(module, "servicedelegationtarget", _target):
module.fail_json(
msg="Service delegation target '%s' does not exist" % _target)
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
principal=dict(required=False, type='list', elements="str",
default=None),
target=dict(required=False, type='list', elements="str",
aliases=["servicedelegationtarget"], default=None),
action=dict(type="str", default="servicedelegationrule",
choices=["member", "servicedelegationrule"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
principal = ansible_module.params_get("principal")
target = ansible_module.params_get("target")
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one servicedelegationrule can be added at a time.")
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
if action == "servicedelegationrule":
invalid = ["principal", "target"]
ansible_module.params_fail_used_invalid(invalid, state, action)
# Init
membertarget = "ipaallowedtarget_servicedelegationtarget"
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
# Normalize principals
if principal:
principal = servicedelegation_normalize_principals(
ansible_module, principal, state == "present")
if target and state == "present":
check_targets(ansible_module, target)
commands = []
principal_add = principal_del = []
target_add = target_del = []
for name in names:
# Make sure servicedelegationrule exists
res_find = find_servicedelegationrule(ansible_module, name)
# Create command
if state == "present":
if action == "servicedelegationrule":
# A servicedelegationrule does not have normal options.
# There is no servicedelegationtarget-mod command.
# Principal members are handled with the _add_member and
# _remove_member commands further down.
if res_find is None:
commands.append([name, "servicedelegationrule_add",
{}])
res_find = {}
# Generate addition and removal lists for principal
principal_add, principal_del = gen_add_del_lists(
principal, res_find.get("memberprincipal"))
# Generate addition and removal lists for target
target_add, target_del = gen_add_del_lists(
target, res_find.get(membertarget))
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No servicedelegationrule '%s'" % name)
# Reduce add lists for principal
# to new entries only that are not in res_find.
if principal is not None and \
"memberprincipal" in res_find:
principal_add = gen_add_list(
principal, res_find["memberprincipal"])
else:
principal_add = principal
# Reduce add lists for target
# to new entries only that are not in res_find.
if target is not None and membertarget in res_find:
target_add = gen_add_list(
target, res_find[membertarget])
else:
target_add = target
elif state == "absent":
if action == "servicedelegationrule":
if res_find is not None:
commands.append([name, "servicedelegationrule_del",
{}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No servicedelegationrule '%s'" % name)
# Reduce del lists of principals to the entries only
# that are in res_find.
if principal is not None:
principal_del = gen_intersection_list(
principal, res_find.get("memberprincipal"))
else:
principal_del = principal
# Reduce del lists of targets to the entries only
# that are in res_find.
if target is not None:
target_del = gen_intersection_list(
target, res_find.get(membertarget))
else:
target_del = target
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Handle members
# Add principal members
if principal_add is not None and len(principal_add) > 0:
commands.append(
[name, "servicedelegationtarget_add_member",
{
"principal": principal_add,
}])
# Remove principal members
if principal_del is not None and len(principal_del) > 0:
commands.append(
[name, "servicedelegationtarget_remove_member",
{
"principal": principal_del,
}])
# Add target members
if target_add is not None and len(target_add) > 0:
commands.append(
[name, "servicedelegationrule_add_target",
{
"servicedelegationtarget": target_add,
}])
# Remove target members
if target_del is not None and len(target_del) > 0:
commands.append(
[name, "servicedelegationrule_remove_target",
{
"servicedelegationtarget": target_del,
}])
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipaservicedelegationtarget.py 0000664 0000000 0000000 00000021560 14600563364 0026510 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaservicedelegationtarget
short_description: Manage FreeIPA servicedelegationtarget
description: |
Manage FreeIPA servicedelegationtarget and servicedelegationtarget members
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of servicedelegationtarget name strings.
type: list
elements: str
required: true
aliases: ["cn"]
principal:
description: |
The list of principals. A principal can be of the format:
fqdn, fqdn@REALM, service/fqdn, service/fqdn@REALM, host/fqdn,
host/fqdn@REALM, alias$, alias$@REALM, where fqdn and fqdn@REALM
are host principals and the same as host/fqdn and host/fqdn@REALM.
Host princpals are only usable with IPA versions 4.9.0 and up.
type: list
elements: str
required: false
action:
description: Work on servicedelegationtarget or member level.
type: str
choices: ["servicedelegationtarget", "member"]
default: servicedelegationtarget
required: false
state:
description: The state to ensure.
type: str
choices: ["present", "absent"]
default: present
required: false
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure servicedelegationtarget delegation-target is present
- ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
name: delegation-target
# Ensure servicedelegationtarget delegation-target member principal
# test/example.com is present
- ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
name: delegation-target
principal: test/example.com
action: member
# Ensure servicedelegationtarget delegation-target member principal
# test/example.com is absent
- ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
name: delegation-target
principal: test/example.com
action: member
state: absent
# Ensure servicedelegationtarget delegation-target is absent
- ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
name: delegation-target
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, gen_add_del_lists, gen_add_list, gen_intersection_list, \
servicedelegation_normalize_principals
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_servicedelegationtarget(module, name):
"""Find if a servicedelegationtarget with the given name already exist."""
try:
_result = module.ipa_command("servicedelegationtarget_show", name,
{"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if servicedelegationtarget name is not found.
return None
return _result["result"]
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
principal=dict(required=False, type='list', elements="str",
default=None),
action=dict(type="str", default="servicedelegationtarget",
choices=["member", "servicedelegationtarget"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
principal = ansible_module.params_get("principal")
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one servicedelegationtarget can be added at a time.")
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
if action == "servicedelegationtarget":
invalid.append("principal")
ansible_module.params_fail_used_invalid(invalid, state, action)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
# Normalize principals
if principal:
principal = servicedelegation_normalize_principals(
ansible_module, principal, state == "present")
commands = []
principal_add = principal_del = []
for name in names:
# Make sure servicedelegationtarget exists
res_find = find_servicedelegationtarget(ansible_module, name)
# Create command
if state == "present":
if action == "servicedelegationtarget":
# A servicedelegationtarget does not have normal options.
# There is no servicedelegationtarget-mod command.
# Principal members are handled with the _add_member and
# _remove_member commands further down.
if res_find is None:
commands.append([name, "servicedelegationtarget_add",
{}])
res_find = {}
# Generate addition and removal lists
principal_add, principal_del = gen_add_del_lists(
principal, res_find.get("memberprincipal"))
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No servicedelegationtarget '%s'" % name)
# Reduce add lists for principal
# to new entries only that are not in res_find.
if principal is not None and \
"memberprincipal" in res_find:
principal_add = gen_add_list(
principal, res_find["memberprincipal"])
else:
principal_add = principal
elif state == "absent":
if action == "servicedelegationtarget":
if res_find is not None:
commands.append([name, "servicedelegationtarget_del",
{}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No servicedelegationtarget '%s'" % name)
# Reduce del lists of principal
# to the entries only that are in res_find.
if principal is not None:
principal_del = gen_intersection_list(
principal, res_find.get("memberprincipal"))
else:
principal_del = principal
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Handle members
# Add principal members
if principal_add is not None and len(principal_add) > 0:
commands.append(
[name, "servicedelegationtarget_add_member",
{
"principal": principal_add,
}])
# Remove principal members
if principal_del is not None and len(principal_del) > 0:
commands.append(
[name, "servicedelegationtarget_remove_member",
{
"principal": principal_del,
}])
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipasudocmd.py 0000664 0000000 0000000 00000011362 14600563364 0023242 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipasudocmd
short_description: Manage FreeIPA sudo command
description: Manage FreeIPA sudo command
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The sudo command
type: list
elements: str
required: true
aliases: ["sudocmd"]
description:
description: The command description
type: str
required: false
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent"]
author:
- Rafael Guterres Jeffman (@rjeffman)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure sudocmd is present
- ipasudocmd:
ipaadmin_password: SomeADMINpassword
name: /usr/bin/su
state: present
# Ensure sudocmd is absent
- ipasudocmd:
ipaadmin_password: SomeADMINpassword
name: /usr/bin/su
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa
def find_sudocmd(module, name):
_args = {
"all": True,
"sudocmd": name,
}
_result = module.ipa_command("sudocmd_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one sudocmd '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
return None
def gen_args(description):
_args = {}
if description is not None:
_args["description"] = description
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["sudocmd"],
required=True),
# present
description=dict(type="str", default=None),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
description = ansible_module.params_get("description")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "absent":
invalid = ["description"]
ansible_module.params_fail_used_invalid(invalid, state)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
# Make sure hostgroup exists
res_find = find_sudocmd(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description)
if res_find is not None:
# For all settings in args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "sudocmd_mod", args])
else:
commands.append([name, "sudocmd_add", args])
# Set res_find to empty dict for next step
res_find = {}
elif state == "absent":
if res_find is not None:
commands.append([name, "sudocmd_del", {}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
changed = ansible_module.execute_ipa_commands(commands)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipasudocmdgroup.py 0000664 0000000 0000000 00000022351 14600563364 0024317 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipasudocmdgroup
short_description: Manage FreeIPA sudocmd groups
description: Manage FreeIPA sudocmd groups
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The sudocmodgroup name
type: list
elements: str
required: true
aliases: ["cn"]
description:
description: The sudocmdgroup description
type: str
required: false
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
sudocmd:
description: List of sudocmds assigned to this sudocmdgroup.
required: false
type: list
elements: str
action:
description: Work on sudocmdgroup or member level
type: str
default: sudocmdgroup
choices: ["member", "sudocmdgroup"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent"]
author:
- Rafael Guterres Jeffman (@rjeffman)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure sudocmd-group 'network' is present
- ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
name: network
state: present
# Ensure sudocmdgroup and sudocmd are present in 'network' sudocmdgroup
- ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member
# Ensure sudocmdgroup and sudocmd are absent in 'network' sudocmdgroup
- ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member
state: absent
# Ensure sudocmd-group 'network' is absent
- ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
name: network
action: member
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, \
gen_add_list, gen_intersection_list, ipalib_errors
def find_sudocmdgroup(module, name):
args = {"all": True}
try:
_result = module.ipa_command("sudocmdgroup_show", name, args)
except ipalib_errors.NotFound:
return None
return _result["result"]
def gen_args(description, nomembers):
_args = {}
if description is not None:
_args["description"] = description
if nomembers is not None:
_args["nomembers"] = nomembers
return _args
def gen_member_args(sudocmd):
_args = {}
if sudocmd is not None:
_args["member_sudocmd"] = sudocmd
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
description=dict(type="str", default=None),
nomembers=dict(required=False, type='bool', default=None),
sudocmd=dict(required=False, type='list', elements="str",
default=None),
action=dict(type="str", default="sudocmdgroup",
choices=["member", "sudocmdgroup"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
description = ansible_module.params_get("description")
nomembers = ansible_module.params_get("nomembers")
sudocmd = ansible_module.params_get("sudocmd")
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one sudocmdgroup can be added at a time.")
if action == "member":
invalid = ["description", "nomembers"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(
msg="No name given.")
invalid = ["description", "nomembers"]
if action == "sudocmdgroup":
invalid.extend(["sudocmd"])
ansible_module.params_fail_used_invalid(invalid, state, action)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
commands = []
for name in names:
# Make sure hostgroup exists
res_find = find_sudocmdgroup(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description, nomembers)
if action == "sudocmdgroup":
# Found the hostgroup
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "sudocmdgroup_mod", args])
else:
commands.append([name, "sudocmdgroup_add", args])
# Set res_find to empty dict for next step
res_find = {}
member_args = gen_member_args(sudocmd)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
sudocmd_add, sudocmd_del = \
gen_add_del_lists(
sudocmd,
res_find.get("member_sudocmd"))
# Add members
if len(sudocmd_add) > 0:
commands.append([name, "sudocmdgroup_add_member",
{
"sudocmd": sudocmd_add
}
])
# Remove members
if len(sudocmd_del) > 0:
commands.append([name,
"sudocmdgroup_remove_member",
{
"sudocmd": sudocmd_del
}
])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No sudocmdgroup '%s'" % name)
# Ensure members are present
sudocmd = gen_add_list(
sudocmd, res_find.get("member_sudocmd") or [])
if sudocmd:
commands.append([name, "sudocmdgroup_add_member",
{"sudocmd": sudocmd}
])
elif state == "absent":
if action == "sudocmdgroup":
if res_find is not None:
commands.append([name, "sudocmdgroup_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No sudocmdgroup '%s'" % name)
sudocmd = gen_intersection_list(
sudocmd, res_find.get("member_sudocmd") or [])
if sudocmd:
commands.append([name, "sudocmdgroup_remove_member",
{"sudocmd": sudocmd}
])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipasudorule.py 0000664 0000000 0000000 00000106755 14600563364 0023461 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipasudorule
short_description: Manage FreeIPA sudo rules
description: Manage FreeIPA sudo rules
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The sudorule name
type: list
elements: str
required: true
aliases: ["cn"]
description:
description: The sudorule description
type: str
required: false
user:
description: List of users assigned to the sudo rule.
type: list
elements: str
required: false
usercategory:
description: User category the sudo rule applies to
type: str
required: false
choices: ["all", ""]
aliases: ["usercat"]
group:
description: List of user groups assigned to the sudo rule.
type: list
elements: str
required: false
runasgroupcategory:
description: RunAs Group category applied to the sudo rule.
type: str
required: false
choices: ["all", ""]
aliases: ["runasgroupcat"]
runasusercategory:
description: RunAs User category applied to the sudorule.
type: str
required: false
choices: ["all", ""]
aliases: ["runasusercat"]
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
host:
description: List of host names assigned to this sudorule.
required: false
type: list
elements: str
hostgroup:
description: List of host groups assigned to this sudorule.
required: false
type: list
elements: str
hostcategory:
description: Host category the sudo rule applies to.
type: str
required: false
choices: ["all", ""]
aliases: ["hostcat"]
allow_sudocmd:
description: List of allowed sudocmds assigned to this sudorule.
required: false
type: list
elements: str
allow_sudocmdgroup:
description: List of allowed sudocmd groups assigned to this sudorule.
required: false
type: list
elements: str
deny_sudocmd:
description: List of denied sudocmds assigned to this sudorule.
required: false
type: list
elements: str
deny_sudocmdgroup:
description: List of denied sudocmd groups assigned to this sudorule.
required: false
type: list
elements: str
cmdcategory:
description: Command category the sudo rule applies to
type: str
required: false
choices: ["all", ""]
aliases: ["cmdcat"]
order:
description: Order to apply this rule.
required: false
type: int
aliases: ["sudoorder"]
sudooption:
description: List of sudo options.
required: false
type: list
elements: str
aliases: ["options"]
runasuser:
description: List of users for Sudo to execute as.
required: false
type: list
elements: str
runasuser_group:
description: List of groups for Sudo to execute as.
required: false
type: list
elements: str
runasgroup:
description: List of groups for Sudo to execute as.
required: false
type: list
elements: str
hostmask:
description: Host masks of allowed hosts.
required: false
type: list
elements: str
action:
description: Work on sudorule or member level
type: str
default: sudorule
choices: ["member", "sudorule"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent", "enabled", "disabled"]
author:
- Rafael Guterres Jeffman (@rjeffman)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure Sudo Rule tesrule1 is present
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
# Ensure sudocmd is present in Sudo Rule
- ipasudorule:
ipaadmin_password: pass1234
name: testrule1
allow_sudocmd:
- /sbin/ifconfig
- /usr/bin/vim
action: member
state: absent
# Ensure host server is present in Sudo Rule
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
host: server
action: member
# Ensure hostgroup cluster is present in Sudo Rule
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
hostgroup: cluster
action: member
# Ensure sudo rule for usercategory "all" is enabled
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
usercategory: all
state: enabled
# Ensure sudo rule for hostcategory "all" is enabled
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allhosts
hostcategory: all
state: enabled
# Ensure sudo rule applies for hosts with hostmasks
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
hostmask:
- 192.168.122.1/24
- 192.168.120.1/24
# Ensure sudorule 'runasuser' has 'ipasuers' group as runas users.
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
runasuser_group: ipausers
action: member
# Ensure Sudo Rule tesrule1 is absent
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule1
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
gen_intersection_list, api_get_domain, ensure_fqdn, netaddr, to_text
def find_sudorule(module, name):
_args = {
"all": True,
"cn": name,
}
_result = module.ipa_command("sudorule_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one sudorule '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
return None
def gen_args(description, usercat, hostcat, cmdcat, runasusercat,
runasgroupcat, order, nomembers):
_args = {}
if description is not None:
_args['description'] = description
if usercat is not None:
_args['usercategory'] = usercat
if hostcat is not None:
_args['hostcategory'] = hostcat
if cmdcat is not None:
_args['cmdcategory'] = cmdcat
if runasusercat is not None:
_args['ipasudorunasusercategory'] = runasusercat
if runasgroupcat is not None:
_args['ipasudorunasgroupcategory'] = runasgroupcat
if order is not None:
_args['sudoorder'] = order
if nomembers is not None:
_args['nomembers'] = nomembers
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
# present
description=dict(required=False, type="str", default=None),
usercategory=dict(required=False, type="str", default=None,
choices=["all", ""], aliases=['usercat']),
hostcategory=dict(required=False, type="str", default=None,
choices=["all", ""], aliases=['hostcat']),
nomembers=dict(required=False, type='bool', default=None),
host=dict(required=False, type='list', elements="str",
default=None),
hostgroup=dict(required=False, type='list', elements="str",
default=None),
hostmask=dict(required=False, type='list', elements="str",
default=None),
user=dict(required=False, type='list', elements="str",
default=None),
group=dict(required=False, type='list', elements="str",
default=None),
allow_sudocmd=dict(required=False, type="list", elements="str",
default=None),
deny_sudocmd=dict(required=False, type="list", elements="str",
default=None),
allow_sudocmdgroup=dict(required=False, type="list",
elements="str", default=None),
deny_sudocmdgroup=dict(required=False, type="list", elements="str",
default=None),
cmdcategory=dict(required=False, type="str", default=None,
choices=["all", ""], aliases=['cmdcat']),
runasusercategory=dict(required=False, type="str", default=None,
choices=["all", ""],
aliases=['runasusercat']),
runasgroupcategory=dict(required=False, type="str", default=None,
choices=["all", ""],
aliases=['runasgroupcat']),
runasuser=dict(required=False, type="list", elements="str",
default=None),
runasgroup=dict(required=False, type="list", elements="str",
default=None),
runasuser_group=dict(required=False, type="list", elements="str",
default=None),
order=dict(type="int", required=False, aliases=['sudoorder']),
sudooption=dict(required=False, type='list', elements="str",
default=None, aliases=["options"]),
action=dict(type="str", default="sudorule",
choices=["member", "sudorule"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent",
"enabled", "disabled"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
# present
# The 'noqa' variables are not used here, but required for vars().
# The use of 'noqa' ensures flake8 does not complain about them.
description = ansible_module.params_get("description") # noqa
cmdcategory = ansible_module.params_get('cmdcategory') # noqa
usercategory = ansible_module.params_get("usercategory") # noqa
hostcategory = ansible_module.params_get("hostcategory") # noqa
runasusercategory = ansible_module.params_get( # noqa
"runasusercategory")
runasgroupcategory = ansible_module.params_get( # noqa
"runasgroupcategory")
hostcategory = ansible_module.params_get("hostcategory") # noqa
nomembers = ansible_module.params_get("nomembers") # noqa
host = ansible_module.params_get("host")
hostgroup = ansible_module.params_get_lowercase("hostgroup")
hostmask = ansible_module.params_get("hostmask")
user = ansible_module.params_get_lowercase("user")
group = ansible_module.params_get_lowercase("group")
allow_sudocmd = ansible_module.params_get('allow_sudocmd')
allow_sudocmdgroup = \
ansible_module.params_get_lowercase('allow_sudocmdgroup')
deny_sudocmd = ansible_module.params_get('deny_sudocmd')
deny_sudocmdgroup = \
ansible_module.params_get_lowercase('deny_sudocmdgroup')
sudooption = ansible_module.params_get("sudooption")
order = ansible_module.params_get("order")
runasuser = ansible_module.params_get_lowercase("runasuser")
runasuser_group = ansible_module.params_get_lowercase("runasuser_group")
runasgroup = ansible_module.params_get_lowercase("runasgroup")
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
# ensure hostmasks are network cidr
if hostmask is not None:
hostmask = [to_text(netaddr.IPNetwork(x).cidr) for x in hostmask]
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one sudorule can be added at a time.")
if action == "member":
invalid = ["description", "usercategory", "hostcategory",
"cmdcategory", "runasusercategory",
"runasgroupcategory", "order", "nomembers"]
else:
if hostcategory == 'all' and any([host, hostgroup]):
ansible_module.fail_json(
msg="Hosts cannot be added when host category='all'")
if usercategory == 'all' and any([user, group]):
ansible_module.fail_json(
msg="Users cannot be added when user category='all'")
if cmdcategory == 'all' \
and any([allow_sudocmd, allow_sudocmdgroup]):
ansible_module.fail_json(
msg="Commands cannot be added when command category='all'")
elif state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description", "usercategory", "hostcategory",
"cmdcategory", "runasusercategory",
"runasgroupcategory", "nomembers", "order"]
if action == "sudorule":
invalid.extend(["host", "hostgroup", "hostmask", "user", "group",
"runasuser", "runasgroup", "allow_sudocmd",
"allow_sudocmdgroup", "deny_sudocmd",
"deny_sudocmdgroup", "sudooption",
"runasuser_group"])
elif state in ["enabled", "disabled"]:
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
if action == "member":
ansible_module.fail_json(
msg="Action member can not be used with states enabled and "
"disabled")
invalid = ["description", "usercategory", "hostcategory",
"cmdcategory", "runasusercategory", "runasgroupcategory",
"nomembers", "nomembers", "host", "hostgroup", "hostmask",
"user", "group", "allow_sudocmd", "allow_sudocmdgroup",
"deny_sudocmd", "deny_sudocmdgroup", "runasuser",
"runasgroup", "order", "sudooption", "runasuser_group"]
else:
ansible_module.fail_json(msg="Invalid state '%s'" % state)
ansible_module.params_fail_used_invalid(invalid, state, action)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
default_domain = api_get_domain()
# Ensure host is not short hostname.
if host:
host = list(
{ensure_fqdn(value.lower(), default_domain) for value in host}
)
commands = []
host_add, host_del = [], []
user_add, user_del = [], []
group_add, group_del = [], []
hostgroup_add, hostgroup_del = [], []
hostmask_add, hostmask_del = [], []
allow_cmd_add, allow_cmd_del = [], []
allow_cmdgroup_add, allow_cmdgroup_del = [], []
deny_cmd_add, deny_cmd_del = [], []
deny_cmdgroup_add, deny_cmdgroup_del = [], []
sudooption_add, sudooption_del = [], []
runasuser_add, runasuser_del = [], []
runasuser_group_add, runasuser_group_del = [], []
runasgroup_add, runasgroup_del = [], []
for name in names:
# Make sure sudorule exists
res_find = find_sudorule(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description, usercategory, hostcategory,
cmdcategory, runasusercategory,
runasgroupcategory, order, nomembers)
if action == "sudorule":
# Found the sudorule
if res_find is not None:
# Remove empty usercategory, hostcategory,
# cmdcaterory, runasusercategory and hostcategory
# from args if "" and if the category is not in the
# sudorule. The empty string is used to reset the
# category.
if "usercategory" in args \
and args["usercategory"] == "" \
and "usercategory" not in res_find:
del args["usercategory"]
if "hostcategory" in args \
and args["hostcategory"] == "" \
and "hostcategory" not in res_find:
del args["hostcategory"]
if "cmdcategory" in args \
and args["cmdcategory"] == "" \
and "cmdcategory" not in res_find:
del args["cmdcategory"]
if "ipasudorunasusercategory" in args \
and args["ipasudorunasusercategory"] == "" \
and "ipasudorunasusercategory" not in res_find:
del args["ipasudorunasusercategory"]
if "ipasudorunasgroupcategory" in args \
and args["ipasudorunasgroupcategory"] == "" \
and "ipasudorunasgroupcategory" not in res_find:
del args["ipasudorunasgroupcategory"]
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "sudorule_mod", args])
else:
commands.append([name, "sudorule_add", args])
# Set res_find to empty dict for next step
res_find = {}
# Generate addition and removal lists
host_add, host_del = gen_add_del_lists(
host, res_find.get('memberhost_host', []))
hostgroup_add, hostgroup_del = gen_add_del_lists(
hostgroup, res_find.get('memberhost_hostgroup', []))
hostmask_add, hostmask_del = gen_add_del_lists(
hostmask, res_find.get('hostmask', []))
user_add, user_del = gen_add_del_lists(
user, res_find.get('memberuser_user', []))
group_add, group_del = gen_add_del_lists(
group, res_find.get('memberuser_group', []))
allow_cmd_add, allow_cmd_del = gen_add_del_lists(
allow_sudocmd,
res_find.get('memberallowcmd_sudocmd', []))
allow_cmdgroup_add, allow_cmdgroup_del = gen_add_del_lists(
allow_sudocmdgroup,
res_find.get('memberallowcmd_sudocmdgroup', []))
deny_cmd_add, deny_cmd_del = gen_add_del_lists(
deny_sudocmd,
res_find.get('memberdenycmd_sudocmd', []))
deny_cmdgroup_add, deny_cmdgroup_del = gen_add_del_lists(
deny_sudocmdgroup,
res_find.get('memberdenycmd_sudocmdgroup', []))
sudooption_add, sudooption_del = gen_add_del_lists(
sudooption, res_find.get('ipasudoopt', []))
# runasuser attribute can be used with both IPA and
# non-IPA (external) users. IPA will handle the correct
# attribute to properly store data, so we need to compare
# the provided list against both users and external
# users list.
runasuser_add, runasuser_del = gen_add_del_lists(
runasuser,
(
res_find.get('ipasudorunas_user', [])
+ res_find.get('ipasudorunasextuser', [])
)
)
runasuser_group_add, runasuser_group_del = (
gen_add_del_lists(
runasuser_group,
res_find.get('ipasudorunas_group', [])
)
)
# runasgroup attribute can be used with both IPA and
# non-IPA (external) groups. IPA will handle the correct
# attribute to properly store data, so we need to compare
# the provided list against both groups and external
# groups list.
runasgroup_add, runasgroup_del = gen_add_del_lists(
runasgroup,
(
res_find.get('ipasudorunasgroup_group', [])
+ res_find.get('ipasudorunasextgroup', [])
)
)
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No sudorule '%s'" % name)
# Generate add lists for host, hostgroup, user, group,
# allow_sudocmd, allow_sudocmdgroup, deny_sudocmd,
# deny_sudocmdgroup, sudooption, runasuser, runasgroup
# and res_find to only try to add the items that not in
# the sudorule already
if host is not None:
host_add = gen_add_list(
host, res_find.get("memberhost_host"))
if hostgroup is not None:
hostgroup_add = gen_add_list(
hostgroup, res_find.get("memberhost_hostgroup"))
if hostmask is not None:
hostmask_add = gen_add_list(
hostmask, res_find.get("hostmask"))
if user is not None:
user_add = gen_add_list(
user, res_find.get("memberuser_user"))
if group is not None:
group_add = gen_add_list(
group, res_find.get("memberuser_group"))
if allow_sudocmd is not None:
allow_cmd_add = gen_add_list(
allow_sudocmd,
res_find.get("memberallowcmd_sudocmd")
)
if allow_sudocmdgroup is not None:
allow_cmdgroup_add = gen_add_list(
allow_sudocmdgroup,
res_find.get("memberallowcmd_sudocmdgroup")
)
if deny_sudocmd is not None:
deny_cmd_add = gen_add_list(
deny_sudocmd,
res_find.get("memberdenycmd_sudocmd")
)
if deny_sudocmdgroup is not None:
deny_cmdgroup_add = gen_add_list(
deny_sudocmdgroup,
res_find.get("memberdenycmd_sudocmdgroup")
)
if sudooption is not None:
sudooption_add = gen_add_list(
sudooption, res_find.get("ipasudoopt"))
# runasuser attribute can be used with both IPA and
# non-IPA (external) users, so we need to compare
# the provided list against both users and external
# users list.
if runasuser is not None:
runasuser_add = gen_add_list(
runasuser,
(list(res_find.get('ipasudorunas_user', []))
+ list(res_find.get('ipasudorunasextuser', [])))
)
if runasuser_group is not None:
runasuser_group_add = gen_add_list(
runasuser_group,
res_find.get('ipasudorunas_group', [])
)
# runasgroup attribute can be used with both IPA and
# non-IPA (external) groups, so we need to compare
# the provided list against both users and external
# groups list.
if runasgroup is not None:
runasgroup_add = gen_add_list(
runasgroup,
(list(res_find.get("ipasudorunasgroup_group", []))
+ list(res_find.get("ipasudorunasextgroup", [])))
)
elif state == "absent":
if action == "sudorule":
if res_find is not None:
commands.append([name, "sudorule_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No sudorule '%s'" % name)
# Generate intersection lists for host, hostgroup, user,
# group, allow_sudocmd, allow_sudocmdgroup, deny_sudocmd
# deny_sudocmdgroup, sudooption, runasuser, runasgroup
# and res_find to only try to remove the items that are
# in sudorule
if host is not None:
host_del = gen_intersection_list(
host, res_find.get("memberhost_host"))
if hostgroup is not None:
hostgroup_del = gen_intersection_list(
hostgroup, res_find.get("memberhost_hostgroup"))
if hostmask is not None:
hostmask_del = gen_intersection_list(
hostmask, res_find.get("hostmask"))
if user is not None:
user_del = gen_intersection_list(
user, res_find.get("memberuser_user"))
if group is not None:
group_del = gen_intersection_list(
group, res_find.get("memberuser_group"))
if allow_sudocmd is not None:
allow_cmd_del = gen_intersection_list(
allow_sudocmd,
res_find.get("memberallowcmd_sudocmd")
)
if allow_sudocmdgroup is not None:
allow_cmdgroup_del = gen_intersection_list(
allow_sudocmdgroup,
res_find.get("memberallowcmd_sudocmdgroup")
)
if deny_sudocmd is not None:
deny_cmd_del = gen_intersection_list(
deny_sudocmd,
res_find.get("memberdenycmd_sudocmd")
)
if deny_sudocmdgroup is not None:
deny_cmdgroup_del = gen_intersection_list(
deny_sudocmdgroup,
res_find.get("memberdenycmd_sudocmdgroup")
)
if sudooption is not None:
sudooption_del = gen_intersection_list(
sudooption, res_find.get("ipasudoopt"))
# runasuser attribute can be used with both IPA and
# non-IPA (external) users, so we need to compare
# the provided list against both users and external
# users list.
if runasuser is not None:
runasuser_del = gen_intersection_list(
runasuser,
(
list(res_find.get('ipasudorunas_user', []))
+ list(res_find.get('ipasudorunasextuser', []))
)
)
if runasuser_group is not None:
runasuser_group_del = gen_intersection_list(
runasuser_group,
res_find.get('ipasudorunas_group', [])
)
# runasgroup attribute can be used with both IPA and
# non-IPA (external) groups, so we need to compare
# the provided list against both groups and external
# groups list.
if runasgroup is not None:
runasgroup_del = gen_intersection_list(
runasgroup,
(
list(res_find.get(
"ipasudorunasgroup_group", []))
+ list(res_find.get(
"ipasudorunasextgroup", []))
)
)
elif state == "enabled":
if res_find is None:
ansible_module.fail_json(msg="No sudorule '%s'" % name)
# sudorule_enable is not failing on an enabled sudorule
# Therefore it is needed to have a look at the ipaenabledflag
# in res_find.
# FreeIPA 4.9.10+ and 4.10 use proper mapping for
# boolean values, so we need to convert it to str
# for comparison.
# See: https://github.com/freeipa/freeipa/pull/6294
enabled_flag = str(res_find.get("ipaenabledflag", [False])[0])
if enabled_flag.upper() != "TRUE":
commands.append([name, "sudorule_enable", {}])
elif state == "disabled":
if res_find is None:
ansible_module.fail_json(msg="No sudorule '%s'" % name)
# sudorule_disable is not failing on an disabled sudorule
# Therefore it is needed to have a look at the ipaenabledflag
# in res_find.
# FreeIPA 4.9.10+ and 4.10 use proper mapping for
# boolean values, so we need to convert it to str
# for comparison.
# See: https://github.com/freeipa/freeipa/pull/6294
enabled_flag = str(res_find.get("ipaenabledflag", [False])[0])
if enabled_flag.upper() != "FALSE":
commands.append([name, "sudorule_disable", {}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Manage members.
# Manage hosts and hostgroups
if any([host_add, hostgroup_add, hostmask_add]):
params = {"host": host_add, "hostgroup": hostgroup_add}
# An empty Hostmask cannot be used, or IPA API will fail.
if hostmask_add:
params["hostmask"] = hostmask_add
commands.append([name, "sudorule_add_host", params])
if any([host_del, hostgroup_del, hostmask_del]):
params = {"host": host_del, "hostgroup": hostgroup_del}
# An empty Hostmask cannot be used, or IPA API will fail.
if hostmask_del:
params["hostmask"] = hostmask_del
commands.append([name, "sudorule_remove_host", params])
# Manage users and groups
if user_add or group_add:
commands.append([
name, "sudorule_add_user",
{"user": user_add, "group": group_add}
])
if user_del or group_del:
commands.append([
name, "sudorule_remove_user",
{"user": user_del, "group": group_del}
])
# Manage commands allowed
if allow_cmd_add or allow_cmdgroup_add:
commands.append([
name, "sudorule_add_allow_command",
{
"sudocmd": allow_cmd_add,
"sudocmdgroup": allow_cmdgroup_add,
}
])
if allow_cmd_del or allow_cmdgroup_del:
commands.append([
name, "sudorule_remove_allow_command",
{
"sudocmd": allow_cmd_del,
"sudocmdgroup": allow_cmdgroup_del
}
])
# Manage commands denied
if deny_cmd_add or deny_cmdgroup_add:
commands.append([
name, "sudorule_add_deny_command",
{
"sudocmd": deny_cmd_add,
"sudocmdgroup": deny_cmdgroup_add,
}
])
if deny_cmd_del or deny_cmdgroup_del:
commands.append([
name, "sudorule_remove_deny_command",
{
"sudocmd": deny_cmd_del,
"sudocmdgroup": deny_cmdgroup_del
}
])
# Manage RunAS users
if runasuser_add or runasuser_group_add:
# Can't use empty lists with command "sudorule_add_runasuser".
_args = {}
if runasuser_add:
_args["user"] = runasuser_add
if runasuser_group_add:
_args["group"] = runasuser_group_add
commands.append([name, "sudorule_add_runasuser", _args])
if runasuser_del or runasuser_group_del:
commands.append([
name,
"sudorule_remove_runasuser",
{"user": runasuser_del, "group": runasuser_group_del}
])
# Manage RunAS Groups
if runasgroup_add:
commands.append([
name, "sudorule_add_runasgroup", {"group": runasgroup_add}
])
if runasgroup_del:
commands.append([
name, "sudorule_remove_runasgroup",
{"group": runasgroup_del}
])
# Manage sudo options
if sudooption_add:
for option in sudooption_add:
commands.append([
name, "sudorule_add_option", {"ipasudoopt": option}
])
if sudooption_del:
for option in sudooption_del:
commands.append([
name, "sudorule_remove_option", {"ipasudoopt": option}
])
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_errors=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipatopologysegment.py 0000664 0000000 0000000 00000026354 14600563364 0025052 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipatopologysegment
short_description: Manage FreeIPA topology segments
description: Manage FreeIPA topology segments
extends_documentation_fragment:
- ipamodule_base_docs
options:
suffix:
description: Topology suffix
type: str
required: true
choices: ["domain", "ca", "domain+ca"]
name:
description: Topology segment name, unique identifier.
type: str
required: false
aliases: ["cn"]
left:
description: Left replication node - an IPA server
type: str
required: false
aliases: ["leftnode"]
right:
description: Right replication node - an IPA server
type: str
required: false
aliases: ["rightnode"]
direction:
description: The direction a segment will be reinitialized
type: str
required: false
choices: ["left-to-right", "right-to-left"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent", "enabled", "disabled", "reinitialized",
"checked" ]
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
- ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: domain
left: ipaserver.test.local
right: ipareplica1.test.local
state: present
- ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: domain
name: ipaserver.test.local-to-replica1.test.local
state: absent
- ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: domain
left: ipaserver.test.local
right: ipareplica1.test.local
state: absent
- ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: ca
name: ipaserver.test.local-to-replica1.test.local
direction: left-to-right
state: reinitialized
- ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: domain+ca
left: ipaserver.test.local
right: ipareplica1.test.local
state: absent
- ipatopologysegment:
ipaadmin_password: SomeADMINpassword
suffix: domain+ca
left: ipaserver.test.local
right: ipareplica1.test.local
state: checked
"""
RETURN = """
found:
description: List of found segments
returned: if state is checked
type: list
not-found:
description: List of not found segments
returned: if state is checked
type: list
"""
from ansible.module_utils.ansible_freeipa_module import IPAAnsibleModule
def find_left_right(module, suffix, left, right):
_args = {
"iparepltoposegmentleftnode": left,
"iparepltoposegmentrightnode": right,
}
_result = module.ipa_command("topologysegment_find",
suffix, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="Combination of left node '%s' and right node '%s' is "
"not unique for suffix '%s'" % (left, right, suffix))
elif len(_result["result"]) == 1:
return _result["result"][0]
return None
def find_cn(module, suffix, name):
_args = {
"cn": name,
}
_result = module.ipa_command("topologysegment_find",
suffix, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="CN '%s' is not unique for suffix '%s'" % (name, suffix))
elif len(_result["result"]) == 1:
return _result["result"][0]
return None
def find_left_right_cn(module, suffix, left, right, name):
if left is not None and right is not None:
left_right = find_left_right(module, suffix, left, right)
if left_right is not None:
if name is not None and \
left_right["cn"][0] != name:
module.fail_json(
msg="Left and right nodes do not match "
"given name name (cn) '%s'" % name)
return left_right
# else: Nothing to change
elif name is not None:
cn = find_cn(module, suffix, name)
if cn is not None:
return cn
# else: Nothing to change
else:
module.fail_json(
msg="Either left and right or name need to be set.")
return None
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
suffix=dict(type="str", choices=["domain", "ca", "domain+ca"],
required=True),
name=dict(type="str", aliases=["cn"], default=None),
left=dict(type="str", aliases=["leftnode"], default=None),
right=dict(type="str", aliases=["rightnode"], default=None),
direction=dict(type="str", default=None,
choices=["left-to-right", "right-to-left"]),
state=dict(type="str", default="present",
choices=["present", "absent", "enabled", "disabled",
"reinitialized", "checked"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
suffixes = ansible_module.params_get("suffix")
name = ansible_module.params_get("name")
left = ansible_module.params_get("left")
right = ansible_module.params_get("right")
direction = ansible_module.params_get("direction")
state = ansible_module.params_get("state")
# Check parameters
if state != "reinitialized" and direction is not None:
ansible_module.fail_json(
msg="Direction is not supported in this mode.")
# Init
changed = False
exit_args = {}
with ansible_module.ipa_connect():
commands = []
for suffix in suffixes.split("+"):
# Create command
if state in ["present", "enabled"]:
# Make sure topology segment exists
if left is None or right is None:
ansible_module.fail_json(
msg="Left and right need to be set.")
args = {
"iparepltoposegmentleftnode": left,
"iparepltoposegmentrightnode": right,
}
if name is not None:
args["cn"] = name
res_left_right = find_left_right(ansible_module, suffix,
left, right)
if res_left_right is not None:
if name is not None and \
res_left_right["cn"][0] != name:
ansible_module.fail_json(
msg="Left and right nodes already used with "
"different name (cn) '%s'" % res_left_right["cn"])
# Left and right nodes and also the name can not be
# changed
for key in ["iparepltoposegmentleftnode",
"iparepltoposegmentrightnode"]:
if key in args:
del args[key]
if len(args) > 1:
# cn needs to be in args always
commands.append(["topologysegment_mod", args, suffix])
# else: Nothing to change
else:
if name is None:
args["cn"] = "%s-to-%s" % (left, right)
commands.append(["topologysegment_add", args, suffix])
elif state in ["absent", "disabled"]:
# Make sure topology segment does not exist
res_find = find_left_right_cn(ansible_module, suffix,
left, right, name)
if res_find is not None:
# Found either given name or found name from left and right
# node
args = {
"cn": res_find["cn"][0]
}
commands.append(["topologysegment_del", args, suffix])
elif state == "checked":
# Check if topology segment does exists
res_find = find_left_right_cn(ansible_module, suffix,
left, right, name)
if res_find is not None:
# Found either given name or found name from left and right
# node
exit_args.setdefault("found", []).append(suffix)
else:
# Not found
exit_args.setdefault("not-found", []).append(suffix)
elif state == "reinitialized":
# Reinitialize segment
if direction not in ["left-to-right", "right-to-left"]:
ansible_module.fail_json(msg="Unknown direction '%s'" %
direction)
res_find = find_left_right_cn(ansible_module, suffix,
left, right, name)
if res_find is not None:
# Found either given name or found name from left and right
# node
args = {
"cn": res_find["cn"][0]
}
if direction == "left-to-right":
args["left"] = True
elif direction == "right-to-left":
args["right"] = True
commands.append(["topologysegment_reinitialize", args,
suffix])
else:
params = []
if name is not None:
params.append("name=%s" % name)
if left is not None:
params.append("left=%s" % left)
if right is not None:
params.append("right=%s" % right)
ansible_module.fail_json(
msg="No entry '%s' for suffix '%s'" %
(",".join(params), suffix))
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute command
for command, args, _suffix in commands:
ansible_module.ipa_command(command, _suffix, args)
changed = True
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipatopologysuffix.py 0000664 0000000 0000000 00000005015 14600563364 0024703 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipatopologysuffix
short_description: Verify FreeIPA topology suffix
description: Verify FreeIPA topology suffix
extends_documentation_fragment:
- ipamodule_base_docs
options:
suffix:
description: Topology suffix
type: str
required: true
choices: ["domain", "ca"]
state:
description: State to ensure
type: str
default: verified
choices: ["verified"]
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
- ipatopologysuffix:
ipaadmin_password: SomeADMINpassword
suffix: domain
state: verified
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import IPAAnsibleModule
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
suffix=dict(type="str", choices=["domain", "ca"], required=True),
state=dict(type="str", default="verified",
choices=["verified"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
suffix = ansible_module.params_get("suffix")
state = ansible_module.params_get("state")
# Check parameters
# Init
# Create command
if state not in ["verified"]:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute command
with ansible_module.ipa_connect():
# Execute command
ansible_module.ipa_command("topologysuffix_verify", suffix, {})
# Done
ansible_module.exit_json(changed=True)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipatrust.py 0000664 0000000 0000000 00000020255 14600563364 0022766 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rob Verduijn
# Thomas Woerner
#
# Copyright (C) 2019-2022 By Rob Verduijn
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = """
---
module: ipatrust
short_description: Manage FreeIPA Domain Trusts.
description: Manage FreeIPA Domain Trusts.
extends_documentation_fragment:
- ipamodule_base_docs
options:
realm:
description:
- Realm name
type: str
required: true
trust_type:
description:
- Trust type (ad for Active Directory, default)
type: str
default: ad
required: false
choices: ["ad"]
admin:
description:
- Active Directory domain administrator
type: str
required: false
password:
description:
- Active Directory domain administrator's password
type: str
required: false
server:
description:
- Domain controller for the Active Directory domain (optional)
type: str
required: false
trust_secret:
description:
- Shared secret for the trust
type: str
required: false
base_id:
description:
- First Posix ID of the range reserved for the trusted domain
type: int
required: false
range_size:
description:
- Size of the ID range reserved for the trusted domain
type: int
default: 200000
range_type:
description:
- Type of trusted domain ID range, one of ipa-ad-trust, ipa-ad-trust-posix
type: str
choices: ["ipa-ad-trust-posix", "ipa-ad-trust"]
default: ipa-ad-trust
required: false
two_way:
description:
- Establish bi-directional trust. By default trust is inbound one-way only.
type: bool
default: false
required: false
external:
description:
- Establish external trust to a domain in another forest.
- The trust is not transitive beyond the domain.
type: bool
default: false
required: false
state:
description: State to ensure
type: str
default: present
required: false
choices: ["present", "absent"]
author:
- Rob Verduijn (@RobVerduijn)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# add ad-trust
- ipatrust:
ipaadmin_password: SomeADMINpassword
realm: ad.example.test
trust_type: ad
admin: Administrator
password: SomeW1Npassword
state: present
# delete ad-trust
- ipatrust:
ipaadmin_password: SomeADMINpassword
realm: ad.example.test
state: absent
"""
RETURN = """
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule
def find_trust(module, realm):
_args = {
"all": True,
"cn": realm,
}
_result = module.ipa_command("trust_find", realm, _args)
if len(_result["result"]) > 1:
module.fail_json(msg="There is more than one realm '%s'" % (realm))
elif len(_result["result"]) == 1:
return _result["result"][0]
return None
def del_trust(module, realm):
_args = {}
_result = module.ipa_command("trust_del", realm, _args)
if len(_result["result"]["failed"]) > 0:
module.fail_json(
msg="Trust deletion has failed for '%s'" % (realm))
def add_trust(module, realm, args):
_args = args
_result = module.ipa_command("trust_add", realm, _args)
if "cn" not in _result["result"]:
module.fail_json(
msg="Trust add has failed for '%s'" % (realm))
def gen_args(trust_type, admin, password, server, trust_secret, base_id,
range_size, range_type, two_way, external):
_args = {}
if trust_type is not None:
_args["trust_type"] = trust_type
if admin is not None:
_args["realm_admin"] = admin
if password is not None:
_args["realm_passwd"] = password
if server is not None:
_args["realm_server"] = server
if trust_secret is not None:
_args["trust_secret"] = trust_secret
if base_id is not None:
_args["base_id"] = base_id
if range_size is not None:
_args["range_size"] = range_size
if range_type is not None:
_args["range_type"] = range_type
if two_way is not None:
_args["bidirectional"] = two_way
if external is not None:
_args["external"] = external
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
realm=dict(type="str", required=True),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
# present
trust_type=dict(type="str", default="ad", required=False,
choices=["ad"]),
admin=dict(type="str", default=None, required=False),
password=dict(type="str", default=None,
required=False, no_log=True),
server=dict(type="str", default=None, required=False),
trust_secret=dict(type="str", default=None,
required=False, no_log=True),
base_id=dict(type="int", default=None, required=False),
range_size=dict(type="int", default=200000, required=False),
range_type=dict(type="str", default="ipa-ad-trust",
required=False, choices=["ipa-ad-trust-posix",
"ipa-ad-trust"]),
two_way=dict(type="bool", default=False, required=False),
external=dict(type="bool", default=False, required=False),
),
mutually_exclusive=[["trust_secret", "admin"]],
required_together=[["admin", "password"]],
supports_check_mode=True
)
ansible_module._ansible_debug = True
# general
realm = ansible_module.params_get("realm")
# state
state = ansible_module.params_get("state")
# trust
trust_type = ansible_module.params_get("trust_type")
admin = ansible_module.params_get("admin")
password = ansible_module.params_get("password")
server = ansible_module.params_get("server")
trust_secret = ansible_module.params_get("trust_secret")
base_id = ansible_module.params_get("base_id")
range_size = ansible_module.params_get("range_size")
range_type = ansible_module.params_get("range_type")
two_way = ansible_module.params_get("two_way")
external = ansible_module.params_get("external")
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
res_find = find_trust(ansible_module, realm)
if state == "absent":
if res_find is not None:
if not ansible_module.check_mode:
del_trust(ansible_module, realm)
changed = True
elif res_find is None:
if admin is None and trust_secret is None:
ansible_module.fail_json(
msg="one of admin or trust_secret is required when state "
"is present")
else:
args = gen_args(trust_type, admin, password, server,
trust_secret, base_id, range_size, range_type,
two_way, external)
if not ansible_module.check_mode:
add_trust(ansible_module, realm, args)
changed = True
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipauser.py 0000664 0000000 0000000 00000202011 14600563364 0022553 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipauser
short_description: Manage FreeIPA users
description: Manage FreeIPA users
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The list of users (internally uid).
type: list
elements: str
required: false
aliases: ["login"]
users:
description: The list of user dicts (internally uid).
type: list
elements: dict
suboptions:
name:
description: The user (internally uid).
type: str
required: true
aliases: ["login"]
first:
description: The first name. Required if user does not exist.
type: str
required: false
aliases: ["givenname"]
last:
description: The last name. Required if user doesnot exst.
type: str
required: false
aliases: ["sn"]
fullname:
description: The full name
type: str
required: false
aliases: ["cn"]
displayname:
description: The display name
type: str
required: false
initials:
description: Initials
type: str
required: false
homedir:
description: The home directory
type: str
required: false
gecos:
description: The GECOS
type: str
required: false
shell:
description: The login shell
type: str
required: false
aliases: ["loginshell"]
email:
description: List of email addresses
type: list
elements: str
required: false
principal:
description: The kerberos principal
type: list
elements: str
required: false
aliases: ["principalname", "krbprincipalname"]
principalexpiration:
description: |
The kerberos principal expiration date
(possible formats: YYYYMMddHHmmssZ, YYYY-MM-ddTHH:mm:ssZ,
YYYY-MM-ddTHH:mmZ, YYYY-MM-ddZ, YYYY-MM-dd HH:mm:ssZ,
YYYY-MM-dd HH:mmZ) The trailing 'Z' can be skipped.
type: str
required: false
aliases: ["krbprincipalexpiration"]
passwordexpiration:
description: |
The kerberos password expiration date (FreeIPA-4.7+)
(possible formats: YYYYMMddHHmmssZ, YYYY-MM-ddTHH:mm:ssZ,
YYYY-MM-ddTHH:mmZ, YYYY-MM-ddZ, YYYY-MM-dd HH:mm:ssZ,
YYYY-MM-dd HH:mmZ) The trailing 'Z' can be skipped.
Only usable with IPA versions 4.7 and up.
type: str
required: false
aliases: ["krbpasswordexpiration"]
password:
description: The user password
type: str
required: false
random:
description: Generate a random user password
required: false
type: bool
uid:
description: User ID Number (system will assign one if not provided)
type: int
required: false
aliases: ["uidnumber"]
gid:
description: Group ID Number
type: int
required: false
aliases: ["gidnumber"]
street:
description: Street address
type: str
required: false
city:
description: City
type: str
required: false
userstate:
description: State/Province
type: str
required: false
aliases: ["st"]
postalcode:
description: Postalcode/ZIP
type: str
required: false
aliases: ["zip"]
phone:
description: List of telephone numbers
type: list
elements: str
required: false
aliases: ["telephonenumber"]
mobile:
description: List of mobile telephone numbers
type: list
elements: str
required: false
pager:
description: List of pager numbers
type: list
elements: str
required: false
fax:
description: List of fax numbers
type: list
elements: str
required: false
aliases: ["facsimiletelephonenumber"]
orgunit:
description: Org. Unit
type: str
required: false
aliases: ["ou"]
title:
description: The job title
type: str
required: false
manager:
description: List of managers
type: list
elements: str
required: false
carlicense:
description: List of car licenses
type: list
elements: str
required: false
sshpubkey:
description: List of SSH public keys
required: false
type: list
elements: str
aliases: ["ipasshpubkey"]
userauthtype:
description:
List of supported user authentication types
Use empty string to reset userauthtype to the initial value.
type: list
elements: str
choices: ["password", "radius", "otp", "pkinit", "hardened", "idp", ""]
required: false
aliases: ["ipauserauthtype"]
userclass:
description:
- User category
- (semantics placed on this attribute are for local interpretation)
type: list
elements: str
required: false
aliases: ["class"]
radius:
description: RADIUS proxy configuration
type: str
required: false
aliases: ["ipatokenradiusconfiglink"]
radiususer:
description: RADIUS proxy username
type: str
required: false
aliases: ["radiususername", "ipatokenradiususername"]
departmentnumber:
description: Department Number
type: list
elements: str
required: false
employeenumber:
description: Employee Number
type: str
required: false
employeetype:
description: Employee Type
type: str
required: false
smb_logon_script:
description: SMB logon script path
type: str
required: false
aliases: ["ipantlogonscript"]
smb_profile_path:
description: SMB profile path
type: str
required: false
aliases: ["ipantprofilepath"]
smb_home_dir:
description: SMB Home Directory
type: str
required: false
aliases: ["ipanthomedirectory"]
smb_home_drive:
description: SMB Home Directory Drive
type: str
required: false
choices: [
'A:', 'B:', 'C:', 'D:', 'E:', 'F:', 'G:', 'H:', 'I:', 'J:',
'K:', 'L:', 'M:', 'N:', 'O:', 'P:', 'Q:', 'R:', 'S:', 'T:',
'U:', 'V:', 'W:', 'X:', 'Y:', 'Z:', ''
]
aliases: ["ipanthomedirectorydrive"]
preferredlanguage:
description: Preferred Language
type: str
required: false
idp:
description: External IdP configuration
type: str
required: false
aliases: ["ipaidpconfiglink"]
idp_user_id:
description: A string that identifies the user at external IdP
type: str
required: false
aliases: ["ipaidpsub"]
certificate:
description: List of base-64 encoded user certificates
type: list
elements: str
required: false
aliases: ["usercertificate"]
certmapdata:
description:
- List of certificate mappings
- Only usable with IPA versions 4.5 and up.
type: list
elements: dict
suboptions:
certificate:
description: Base-64 encoded user certificate
type: str
required: false
issuer:
description: Issuer of the certificate
type: str
required: false
subject:
description: Subject of the certificate
type: str
required: false
data:
description: Certmap data
type: str
required: false
required: false
noprivate:
description: Don't create user private group
required: false
type: bool
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
rename:
description: Rename the user object
required: false
type: str
aliases: ["new_name"]
required: false
first:
description: The first name. Required if user does not exist.
type: str
required: false
aliases: ["givenname"]
last:
description: The last name. Required if user doesnot exst.
type: str
required: false
aliases: ["sn"]
fullname:
description: The full name
type: str
required: false
aliases: ["cn"]
displayname:
description: The display name
type: str
required: false
initials:
description: Initials
type: str
required: false
homedir:
description: The home directory
type: str
required: false
gecos:
description: The GECOS
type: str
required: false
shell:
description: The login shell
type: str
required: false
aliases: ["loginshell"]
email:
description: List of email addresses
type: list
elements: str
required: false
principal:
description: The kerberos principal
type: list
elements: str
required: false
aliases: ["principalname", "krbprincipalname"]
principalexpiration:
description: |
The kerberos principal expiration date
(possible formats: YYYYMMddHHmmssZ, YYYY-MM-ddTHH:mm:ssZ,
YYYY-MM-ddTHH:mmZ, YYYY-MM-ddZ, YYYY-MM-dd HH:mm:ssZ,
YYYY-MM-dd HH:mmZ) The trailing 'Z' can be skipped.
type: str
required: false
aliases: ["krbprincipalexpiration"]
passwordexpiration:
description: |
The kerberos password expiration date (FreeIPA-4.7+)
(possible formats: YYYYMMddHHmmssZ, YYYY-MM-ddTHH:mm:ssZ,
YYYY-MM-ddTHH:mmZ, YYYY-MM-ddZ, YYYY-MM-dd HH:mm:ssZ,
YYYY-MM-dd HH:mmZ) The trailing 'Z' can be skipped.
Only usable with IPA versions 4.7 and up.
type: str
required: false
aliases: ["krbpasswordexpiration"]
password:
description: The user password
type: str
required: false
random:
description: Generate a random user password
required: false
type: bool
uid:
description: User ID Number (system will assign one if not provided)
type: int
required: false
aliases: ["uidnumber"]
gid:
description: Group ID Number
type: int
required: false
aliases: ["gidnumber"]
street:
description: Street address
type: str
required: false
city:
description: City
type: str
required: false
userstate:
description: State/Province
type: str
required: false
aliases: ["st"]
postalcode:
description: Postalcode/ZIP
type: str
required: false
aliases: ["zip"]
phone:
description: List of telephone numbers
type: list
elements: str
required: false
aliases: ["telephonenumber"]
mobile:
description: List of mobile telephone numbers
type: list
elements: str
required: false
pager:
description: List of pager numbers
type: list
elements: str
required: false
fax:
description: List of fax numbers
type: list
elements: str
required: false
aliases: ["facsimiletelephonenumber"]
orgunit:
description: Org. Unit
type: str
required: false
aliases: ["ou"]
title:
description: The job title
type: str
required: false
manager:
description: List of managers
type: list
elements: str
required: false
carlicense:
description: List of car licenses
type: list
elements: str
required: false
sshpubkey:
description: List of SSH public keys
required: false
type: list
elements: str
aliases: ["ipasshpubkey"]
userauthtype:
description:
List of supported user authentication types
Use empty string to reset userauthtype to the initial value.
type: list
elements: str
choices: ["password", "radius", "otp", "pkinit", "hardened", "idp", ""]
required: false
aliases: ["ipauserauthtype"]
userclass:
description:
- User category
- (semantics placed on this attribute are for local interpretation)
type: list
elements: str
required: false
aliases: ["class"]
radius:
description: RADIUS proxy configuration
type: str
required: false
aliases: ["ipatokenradiusconfiglink"]
radiususer:
description: RADIUS proxy username
type: str
required: false
aliases: ["radiususername", "ipatokenradiususername"]
departmentnumber:
description: Department Number
type: list
elements: str
required: false
employeenumber:
description: Employee Number
type: str
required: false
employeetype:
description: Employee Type
type: str
required: false
smb_logon_script:
description: SMB logon script path
type: str
required: false
aliases: ["ipantlogonscript"]
smb_profile_path:
description: SMB profile path
type: str
required: false
aliases: ["ipantprofilepath"]
smb_home_dir:
description: SMB Home Directory
type: str
required: false
aliases: ["ipanthomedirectory"]
smb_home_drive:
description: SMB Home Directory Drive
type: str
required: false
choices: [
'A:', 'B:', 'C:', 'D:', 'E:', 'F:', 'G:', 'H:', 'I:', 'J:',
'K:', 'L:', 'M:', 'N:', 'O:', 'P:', 'Q:', 'R:', 'S:', 'T:',
'U:', 'V:', 'W:', 'X:', 'Y:', 'Z:', ''
]
aliases: ["ipanthomedirectorydrive"]
preferredlanguage:
description: Preferred Language
type: str
required: false
idp:
description: External IdP configuration
type: str
required: false
aliases: ["ipaidpconfiglink"]
idp_user_id:
description: A string that identifies the user at external IdP
type: str
required: false
aliases: ["ipaidpsub"]
certificate:
description: List of base-64 encoded user certificates
type: list
elements: str
required: false
aliases: ["usercertificate"]
certmapdata:
description:
- List of certificate mappings
- Only usable with IPA versions 4.5 and up.
type: list
elements: dict
suboptions:
certificate:
description: Base-64 encoded user certificate
type: str
required: false
issuer:
description: Issuer of the certificate
type: str
required: false
subject:
description: Subject of the certificate
type: str
required: false
data:
description: Certmap data
type: str
required: false
required: false
noprivate:
description: Don't create user private group
required: false
type: bool
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
rename:
description: Rename the user object
required: false
type: str
aliases: ["new_name"]
preserve:
description: Delete a user, keeping the entry available for future use
required: false
type: bool
update_password:
description:
Set password for a user in present state only on creation or always
type: str
choices: ["always", "on_create"]
required: false
action:
description: Work on user or member level
type: str
default: "user"
choices: ["member", "user"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent",
"enabled", "disabled",
"unlocked", "undeleted",
"renamed"]
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Create user pinky
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
first: pinky
last: Acme
uid: 10001
gid: 100
phone: "+555123457"
email: pinky@acme.com
passwordexpiration: "2023-01-19 23:59:59"
password: "no-brain"
update_password: on_create
# Create user brain
- ipauser:
ipaadmin_password: SomeADMINpassword
name: brain
first: brain
last: Acme
# Create multiple users pinky and brain
- ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: pinky
first: pinky
last: Acme
- name: brain
first: brain
last: Acme
# Delete user pinky, but preserved
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
preserve: yes
state: absent
# Undelete user pinky
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: undeleted
# Disable user pinky
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky,brain
state: disabled
# Enable user pinky and brain
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky,brain
state: enabled
# Remove but preserve user pinky
- ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: pinky
preserve: yes
state: absent
# Remove user pinky and brain
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky,brain
state: disabled
# Ensure a user has SMB attributes
- ipauser:
ipaadmin_password: SomeADMINpassword
name: smbuser
first: SMB
last: User
smb_logon_script: N:\\logonscripts\\startup
smb_profile_path: \\\\server\\profiles\\some_profile
smb_home_dir: \\\\users\\home\\smbuser
smb_home_drive: "U:"
# Rename an existing user
- ipauser:
ipaadmin_password: SomeADMINpassword
name: someuser
rename: anotheruser
state: renamed
"""
RETURN = """
user:
description: User dict with random password
returned: If random is yes and user did not exist or update_password is yes
type: dict
contains:
randompassword:
description: The generated random password
type: str
returned: |
If only one user is handled by the module without using users parameter
name:
description: The user name of the user that got a new random password
returned: |
If several users are handled by the module with the users parameter
type: dict
contains:
randompassword:
description: The generated random password
type: str
returned: always
"""
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, date_format, \
encode_certificate, load_cert_from_str, DN_x500_text, to_text, \
ipalib_errors
from ansible.module_utils import six
if six.PY3:
unicode = str
def find_user(module, name):
_args = {
"all": True,
}
try:
_result = module.ipa_command("user_show", name, _args).get("result")
except ipalib_errors.NotFound:
return None
# Transform each principal to a string
_result["krbprincipalname"] = [
to_text(x) for x in (_result.get("krbprincipalname") or [])
]
_result["usercertificate"] = [
encode_certificate(x) for x in (_result.get("usercertificate") or [])
]
return _result
def gen_args(first, last, fullname, displayname, initials, homedir, gecos,
shell, email, principalexpiration, passwordexpiration, password,
random, uid, gid, street, city, userstate, postalcode, phone,
mobile, pager, fax, orgunit, title, carlicense, sshpubkey,
userauthtype, userclass, radius, radiususer, departmentnumber,
employeenumber, employeetype, preferredlanguage, smb_logon_script,
smb_profile_path, smb_home_dir, smb_home_drive, idp, idp_user_id,
noprivate, nomembers):
# principal, manager, certificate and certmapdata are handled not in here
_args = {}
if first is not None:
_args["givenname"] = first
if last is not None:
_args["sn"] = last
if fullname is not None:
_args["cn"] = fullname
if displayname is not None:
_args["displayname"] = displayname
if initials is not None:
_args["initials"] = initials
if homedir is not None:
_args["homedirectory"] = homedir
if gecos is not None:
_args["gecos"] = gecos
if shell is not None:
_args["loginshell"] = shell
if email is not None and len(email) > 0:
_args["mail"] = email
if principalexpiration is not None:
_args["krbprincipalexpiration"] = principalexpiration
if passwordexpiration is not None:
_args["krbpasswordexpiration"] = passwordexpiration
if password is not None:
_args["userpassword"] = password
if random is not None:
_args["random"] = random
if uid is not None:
_args["uidnumber"] = to_text(str(uid))
if gid is not None:
_args["gidnumber"] = to_text(str(gid))
if street is not None:
_args["street"] = street
if city is not None:
_args["l"] = city
if userstate is not None:
_args["st"] = userstate
if postalcode is not None:
_args["postalcode"] = postalcode
if phone is not None and len(phone) > 0:
_args["telephonenumber"] = phone
if mobile is not None and len(mobile) > 0:
_args["mobile"] = mobile
if pager is not None and len(pager) > 0:
_args["pager"] = pager
if fax is not None and len(fax) > 0:
_args["facsimiletelephonenumber"] = fax
if orgunit is not None:
_args["ou"] = orgunit
if title is not None:
_args["title"] = title
if carlicense is not None and len(carlicense) > 0:
_args["carlicense"] = carlicense
if sshpubkey is not None and len(sshpubkey) > 0:
_args["ipasshpubkey"] = sshpubkey
if userauthtype is not None and len(userauthtype) > 0:
_args["ipauserauthtype"] = userauthtype
if userclass is not None:
_args["userclass"] = userclass
if radius is not None:
_args["ipatokenradiusconfiglink"] = radius
if radiususer is not None:
_args["ipatokenradiususername"] = radiususer
if departmentnumber is not None:
_args["departmentnumber"] = departmentnumber
if employeenumber is not None:
_args["employeenumber"] = employeenumber
if employeetype is not None:
_args["employeetype"] = employeetype
if preferredlanguage is not None:
_args["preferredlanguage"] = preferredlanguage
if idp is not None:
_args["ipaidpconfiglink"] = idp
if idp_user_id is not None:
_args["ipaidpsub"] = idp_user_id
if noprivate is not None:
_args["noprivate"] = noprivate
if nomembers is not None:
_args["no_members"] = nomembers
if smb_logon_script is not None:
_args["ipantlogonscript"] = smb_logon_script
if smb_profile_path is not None:
_args["ipantprofilepath"] = smb_profile_path
if smb_home_dir is not None:
_args["ipanthomedirectory"] = smb_home_dir
if smb_home_drive is not None:
_args["ipanthomedirectorydrive"] = smb_home_drive
return _args
def check_parameters( # pylint: disable=unused-argument
module, state, action, first, last, fullname, displayname, initials,
homedir, gecos, shell, email, principal, principalexpiration,
passwordexpiration, password, random, uid, gid, street, city, phone,
mobile, pager, fax, orgunit, title, manager, carlicense, sshpubkey,
userauthtype, userclass, radius, radiususer, departmentnumber,
employeenumber, employeetype, preferredlanguage, certificate,
certmapdata, noprivate, nomembers, preserve, update_password,
smb_logon_script, smb_profile_path, smb_home_dir, smb_home_drive,
idp, ipa_user_id, rename
):
if state == "present" and action == "user":
invalid = ["preserve"]
else:
invalid = [
"first", "last", "fullname", "displayname", "initials", "homedir",
"shell", "email", "principalexpiration", "passwordexpiration",
"password", "random", "uid", "gid", "street", "city", "phone",
"mobile", "pager", "fax", "orgunit", "title", "carlicense",
"sshpubkey", "userauthtype", "userclass", "radius", "radiususer",
"departmentnumber", "employeenumber", "employeetype",
"preferredlanguage", "noprivate", "nomembers", "update_password",
"gecos", "smb_logon_script", "smb_profile_path", "smb_home_dir",
"smb_home_drive", "idp", "idp_user_id"
]
if state == "present" and action == "member":
invalid.append("preserve")
else:
if action == "user":
invalid.extend(
["principal", "manager", "certificate", "certmapdata"])
if state != "absent" and preserve is not None:
module.fail_json(
msg="Preserve is only possible for state=absent")
if state != "renamed":
invalid.append("rename")
else:
invalid.extend([
"preserve", "principal", "manager", "certificate", "certmapdata",
])
if not rename:
module.fail_json(
msg="A value for attribute 'rename' must be provided.")
if action == "member":
module.fail_json(
msg="Action member can not be used with state: renamed.")
module.params_fail_used_invalid(invalid, state, action)
if certmapdata is not None:
for x in certmapdata:
certificate = x.get("certificate")
issuer = x.get("issuer")
subject = x.get("subject")
data = x.get("data")
if data is not None:
if certificate is not None or issuer is not None or \
subject is not None:
module.fail_json(
msg="certmapdata: data can not be used with "
"certificate, issuer or subject")
check_certmapdata(data)
if certificate is not None \
and (issuer is not None or subject is not None):
module.fail_json(
msg="certmapdata: certificate can not be used with "
"issuer or subject")
if data is None and certificate is None:
if issuer is None:
module.fail_json(msg="certmapdata: issuer is missing")
if subject is None:
module.fail_json(msg="certmapdata: subject is missing")
def check_userauthtype(module, userauthtype):
_invalid = module.ipa_command_invalid_param_choices(
"user_add", "ipauserauthtype", userauthtype)
if _invalid:
module.fail_json(
msg="The use of userauthtype '%s' is not supported "
"by your IPA version" % "','".join(_invalid))
def extend_emails(email, default_email_domain):
if email is not None:
return ["%s@%s" % (_email, default_email_domain)
if "@" not in _email else _email
for _email in email]
return email
def convert_certmapdata(certmapdata):
if certmapdata is None:
return None
_result = []
for x in certmapdata:
certificate = x.get("certificate")
issuer = x.get("issuer")
subject = x.get("subject")
data = x.get("data")
if data is None:
if issuer is None and subject is None:
cert = load_cert_from_str(certificate)
issuer = cert.issuer
subject = cert.subject
_result.append("X509:%s%s" % (DN_x500_text(issuer),
DN_x500_text(subject)))
else:
_result.append(data)
return _result
def check_certmapdata(data):
if not data.startswith("X509:"):
return False
i = data.find("", 4)
s = data.find("", i) # pylint: disable=invalid-name
issuer = data[i + 3:s]
subject = data[s + 3:]
if i < 0 or s < 0 or "CN" not in issuer or "CN" not in subject:
return False
return True
def gen_certmapdata_args(certmapdata):
return {"ipacertmapdata": to_text(certmapdata)}
# pylint: disable=unused-argument
def result_handler(module, result, command, name, args, errors, exit_args,
single_user):
if "random" in args and command in ["user_add", "user_mod"] \
and "randompassword" in result["result"]:
if single_user:
exit_args["randompassword"] = \
result["result"]["randompassword"]
else:
exit_args.setdefault(name, {})["randompassword"] = \
result["result"]["randompassword"]
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
# pylint: disable=unused-argument
def exception_handler(module, ex, errors, exit_args, single_user):
msg = str(ex)
if "already contains" in msg \
or "does not contain" in msg:
return True
# The canonical principal name may not be removed
if "equal to the canonical principal name must" in msg:
return True
return False
def main():
user_spec = dict(
# present
first=dict(type="str", aliases=["givenname"], default=None),
last=dict(type="str", aliases=["sn"], default=None),
fullname=dict(type="str", aliases=["cn"], default=None),
displayname=dict(type="str", default=None),
initials=dict(type="str", default=None),
homedir=dict(type="str", default=None),
gecos=dict(type="str", default=None),
shell=dict(type="str", aliases=["loginshell"], default=None),
email=dict(type="list", elements="str", default=None),
principal=dict(type="list", elements="str",
aliases=["principalname", "krbprincipalname"],
default=None),
principalexpiration=dict(type="str",
aliases=["krbprincipalexpiration"],
default=None),
passwordexpiration=dict(type="str",
aliases=["krbpasswordexpiration"],
default=None, no_log=False),
password=dict(type="str", default=None, no_log=True),
random=dict(type='bool', default=None),
uid=dict(type="int", aliases=["uidnumber"], default=None),
gid=dict(type="int", aliases=["gidnumber"], default=None),
street=dict(type="str", default=None),
city=dict(type="str", default=None),
userstate=dict(type="str", aliases=["st"], default=None),
postalcode=dict(type="str", aliases=["zip"], default=None),
phone=dict(type="list", elements="str", aliases=["telephonenumber"],
default=None),
mobile=dict(type="list", elements="str", default=None),
pager=dict(type="list", elements="str", default=None),
fax=dict(type="list", elements="str",
aliases=["facsimiletelephonenumber"], default=None),
orgunit=dict(type="str", aliases=["ou"], default=None),
title=dict(type="str", default=None),
manager=dict(type="list", elements="str", default=None),
carlicense=dict(type="list", elements="str", default=None),
sshpubkey=dict(type="list", elements="str", aliases=["ipasshpubkey"],
default=None),
userauthtype=dict(type='list', elements="str",
aliases=["ipauserauthtype"], default=None,
choices=["password", "radius", "otp", "pkinit",
"hardened", "idp", ""]),
userclass=dict(type="list", elements="str", aliases=["class"],
default=None),
radius=dict(type="str", aliases=["ipatokenradiusconfiglink"],
default=None),
radiususer=dict(type="str", aliases=["radiususername",
"ipatokenradiususername"],
default=None),
departmentnumber=dict(type="list", elements="str", default=None),
employeenumber=dict(type="str", default=None),
employeetype=dict(type="str", default=None),
smb_logon_script=dict(type="str", default=None,
aliases=["ipantlogonscript"]),
smb_profile_path=dict(type="str", default=None,
aliases=["ipantprofilepath"]),
smb_home_dir=dict(type="str", default=None,
aliases=["ipanthomedirectory"]),
smb_home_drive=dict(type="str", default=None,
choices=[
("%c:" % chr(x))
for x in range(ord('A'), ord('Z') + 1)
] + [""], aliases=["ipanthomedirectorydrive"]),
preferredlanguage=dict(type="str", default=None),
certificate=dict(type="list", elements="str",
aliases=["usercertificate"], default=None),
certmapdata=dict(type="list", default=None,
options=dict(
# Here certificate is a simple string
certificate=dict(type="str", default=None),
issuer=dict(type="str", default=None),
subject=dict(type="str", default=None),
data=dict(type="str", default=None)
),
elements='dict', required=False),
noprivate=dict(type='bool', default=None),
nomembers=dict(type='bool', default=None),
idp=dict(type="str", default=None, aliases=['ipaidpconfiglink']),
idp_user_id=dict(type="str", default=None,
aliases=['ipaidpconfiglink']),
rename=dict(type="str", required=False, default=None,
aliases=["new_name"]),
)
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", elements="str", aliases=["login"],
default=None, required=False),
users=dict(type="list",
default=None,
options=dict(
# Here name is a simple string
name=dict(type="str", required=True,
aliases=["login"]),
# Add user specific parameters
**user_spec
),
elements='dict',
required=False),
# deleted
preserve=dict(required=False, type='bool', default=None),
# mod
update_password=dict(type='str', default=None, no_log=False,
choices=['always', 'on_create']),
# general
action=dict(type="str", default="user",
choices=["member", "user"]),
state=dict(type="str", default="present",
choices=["present", "absent", "enabled", "disabled",
"unlocked", "undeleted", "renamed"]),
# Add user specific parameters for simple use case
**user_spec
),
mutually_exclusive=[["name", "users"]],
required_one_of=[["name", "users"]],
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
names = ansible_module.params_get("name")
users = ansible_module.params_get("users")
# present
first = ansible_module.params_get("first")
last = ansible_module.params_get("last")
fullname = ansible_module.params_get("fullname")
displayname = ansible_module.params_get("displayname")
initials = ansible_module.params_get("initials")
homedir = ansible_module.params_get("homedir")
gecos = ansible_module.params_get("gecos")
shell = ansible_module.params_get("shell")
email = ansible_module.params_get("email")
principal = ansible_module.params_get("principal")
principalexpiration = ansible_module.params_get(
"principalexpiration")
if principalexpiration is not None:
if principalexpiration[:-1] != "Z":
principalexpiration = principalexpiration + "Z"
principalexpiration = date_format(principalexpiration)
passwordexpiration = ansible_module.params_get("passwordexpiration")
if passwordexpiration is not None:
if passwordexpiration[:-1] != "Z":
passwordexpiration = passwordexpiration + "Z"
passwordexpiration = date_format(passwordexpiration)
password = ansible_module.params_get("password")
random = ansible_module.params_get("random")
uid = ansible_module.params_get("uid")
gid = ansible_module.params_get("gid")
street = ansible_module.params_get("street")
city = ansible_module.params_get("city")
userstate = ansible_module.params_get("userstate")
postalcode = ansible_module.params_get("postalcode")
phone = ansible_module.params_get("phone")
mobile = ansible_module.params_get("mobile")
pager = ansible_module.params_get("pager")
fax = ansible_module.params_get("fax")
orgunit = ansible_module.params_get("orgunit")
title = ansible_module.params_get("title")
manager = ansible_module.params_get("manager")
carlicense = ansible_module.params_get("carlicense")
sshpubkey = ansible_module.params_get("sshpubkey",
allow_empty_list_item=True)
userauthtype = ansible_module.params_get("userauthtype",
allow_empty_list_item=True)
userclass = ansible_module.params_get("userclass")
radius = ansible_module.params_get("radius")
radiususer = ansible_module.params_get("radiususer")
departmentnumber = ansible_module.params_get("departmentnumber")
employeenumber = ansible_module.params_get("employeenumber")
employeetype = ansible_module.params_get("employeetype")
preferredlanguage = ansible_module.params_get("preferredlanguage")
smb_logon_script = ansible_module.params_get("smb_logon_script")
smb_profile_path = ansible_module.params_get("smb_profile_path")
smb_home_dir = ansible_module.params_get("smb_home_dir")
smb_home_drive = ansible_module.params_get("smb_home_drive")
idp = ansible_module.params_get("idp")
idp_user_id = ansible_module.params_get("idp_user_id")
certificate = ansible_module.params_get("certificate")
certmapdata = ansible_module.params_get("certmapdata")
noprivate = ansible_module.params_get("noprivate")
nomembers = ansible_module.params_get("nomembers")
# deleted
preserve = ansible_module.params_get("preserve")
# mod
update_password = ansible_module.params_get("update_password")
# rename
rename = ansible_module.params_get("rename")
# general
action = ansible_module.params_get("action")
state = ansible_module.params_get("state")
# Check parameters
if (names is None or len(names) < 1) and \
(users is None or len(users) < 1):
ansible_module.fail_json(msg="One of name and users is required")
if state in ["present", "renamed"]:
if names is not None and len(names) != 1:
act = "renamed" if state == "renamed" else "added"
ansible_module.fail_json(
msg="Only one user can be %s at a time using name." % (act))
# Use users if names is None
if users is not None:
names = users
else:
check_parameters(
ansible_module, state, action,
first, last, fullname, displayname, initials, homedir, gecos,
shell, email,
principal, principalexpiration, passwordexpiration, password,
random,
uid, gid, street, city, phone, mobile, pager, fax, orgunit, title,
manager, carlicense, sshpubkey, userauthtype, userclass, radius,
radiususer, departmentnumber, employeenumber, employeetype,
preferredlanguage, certificate, certmapdata, noprivate, nomembers,
preserve, update_password, smb_logon_script, smb_profile_path,
smb_home_dir, smb_home_drive, idp, idp_user_id, rename,
)
certmapdata = convert_certmapdata(certmapdata)
# Init
changed = False
exit_args = {}
# Connect to IPA API
with ansible_module.ipa_connect():
# Check version specific settings
server_realm = ansible_module.ipa_get_realm()
# Check API specific parameters
check_userauthtype(ansible_module, userauthtype)
# Default email domain
result = ansible_module.ipa_command_no_name("config_show", {})
default_email_domain = result["result"]["ipadefaultemaildomain"][0]
# Extend email addresses
email = extend_emails(email, default_email_domain)
# commands
commands = []
user_set = set()
for user in names:
if isinstance(user, dict):
name = user.get("name")
if name in user_set:
ansible_module.fail_json(
msg="user '%s' is used more than once" % name)
user_set.add(name)
# present
first = user.get("first")
last = user.get("last")
fullname = user.get("fullname")
displayname = user.get("displayname")
initials = user.get("initials")
homedir = user.get("homedir")
gecos = user.get("gecos")
shell = user.get("shell")
email = user.get("email")
principal = user.get("principal")
principalexpiration = user.get("principalexpiration")
if principalexpiration is not None:
if principalexpiration[:-1] != "Z":
principalexpiration = principalexpiration + "Z"
principalexpiration = date_format(principalexpiration)
passwordexpiration = user.get("passwordexpiration")
if passwordexpiration is not None:
if passwordexpiration[:-1] != "Z":
passwordexpiration = passwordexpiration + "Z"
passwordexpiration = date_format(passwordexpiration)
password = user.get("password")
random = user.get("random")
uid = user.get("uid")
gid = user.get("gid")
street = user.get("street")
city = user.get("city")
userstate = user.get("userstate")
postalcode = user.get("postalcode")
phone = user.get("phone")
mobile = user.get("mobile")
pager = user.get("pager")
fax = user.get("fax")
orgunit = user.get("orgunit")
title = user.get("title")
manager = user.get("manager")
carlicense = user.get("carlicense")
sshpubkey = user.get("sshpubkey")
userauthtype = user.get("userauthtype")
userclass = user.get("userclass")
radius = user.get("radius")
radiususer = user.get("radiususer")
departmentnumber = user.get("departmentnumber")
employeenumber = user.get("employeenumber")
employeetype = user.get("employeetype")
preferredlanguage = user.get("preferredlanguage")
smb_logon_script = user.get("smb_logon_script")
smb_profile_path = user.get("smb_profile_path")
smb_home_dir = user.get("smb_home_dir")
smb_home_drive = user.get("smb_home_drive")
idp = user.get("idp")
idp_user_id = user.get("idp_user_id")
rename = user.get("rename")
certificate = user.get("certificate")
certmapdata = user.get("certmapdata")
noprivate = user.get("noprivate")
nomembers = user.get("nomembers")
check_parameters(
ansible_module, state, action,
first, last, fullname, displayname, initials, homedir,
gecos, shell, email, principal, principalexpiration,
passwordexpiration, password, random, uid, gid, street,
city, phone, mobile, pager, fax, orgunit, title, manager,
carlicense, sshpubkey, userauthtype, userclass, radius,
radiususer, departmentnumber, employeenumber,
employeetype, preferredlanguage, certificate,
certmapdata, noprivate, nomembers, preserve,
update_password, smb_logon_script, smb_profile_path,
smb_home_dir, smb_home_drive, idp, idp_user_id, rename,
)
certmapdata = convert_certmapdata(certmapdata)
# Check API specific parameters
check_userauthtype(ansible_module, userauthtype)
# Extend email addresses
email = extend_emails(email, default_email_domain)
elif isinstance(user, (str, unicode)):
name = user
else:
ansible_module.fail_json(msg="User '%s' is not valid" %
repr(user))
# Fix principals: add realm if missing
# We need the connected API for the realm, therefore it can not
# be part of check_parameters as this is used also before the
# connection to the API has been established.
if principal is not None:
principal = [x if "@" in x else x + "@" + server_realm
for x in principal]
# Check passwordexpiration availability.
# We need the connected API for this test, therefore it can not
# be part of check_parameters as this is used also before the
# connection to the API has been established.
if passwordexpiration is not None and \
not ansible_module.ipa_command_param_exists(
"user_add", "krbpasswordexpiration"):
ansible_module.fail_json(
msg="The use of passwordexpiration is not supported by "
"your IPA version")
# Check certmapdata availability.
# We need the connected API for this test, therefore it can not
# be part of check_parameters as this is used also before the
# connection to the API has been established.
if certmapdata is not None and \
not ansible_module.ipa_command_exists("user_add_certmapdata"):
ansible_module.fail_json(
msg="The use of certmapdata is not supported by "
"your IPA version")
# Check if SMB attributes are available
if (
any([
smb_logon_script, smb_profile_path, smb_home_dir,
smb_home_drive
])
and not ansible_module.ipa_command_param_exists(
"user_mod", "ipanthomedirectory"
)
):
ansible_module.fail_json(
msg="The use of smb_logon_script, smb_profile_path, "
"smb_profile_path, and smb_home_drive is not supported "
"by your IPA version")
# Check if IdP support is available
require_idp = (
idp is not None
or idp_user_id is not None
or userauthtype == "idp"
)
has_idp_support = ansible_module.ipa_command_param_exists(
"user_add", "ipaidpconfiglink"
)
if require_idp and not has_idp_support:
ansible_module.fail_json(
msg="Your IPA version does not support External IdP.")
# Make sure user exists
res_find = find_user(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(
first, last, fullname, displayname, initials, homedir,
gecos,
shell, email, principalexpiration, passwordexpiration,
password, random, uid, gid, street, city, userstate,
postalcode, phone, mobile, pager, fax, orgunit, title,
carlicense, sshpubkey, userauthtype, userclass, radius,
radiususer, departmentnumber, employeenumber, employeetype,
preferredlanguage, smb_logon_script, smb_profile_path,
smb_home_dir, smb_home_drive, idp, idp_user_id, noprivate,
nomembers,
)
if action == "user":
# Found the user
if res_find is not None:
# Ignore password and random with
# update_password == on_create
if update_password == "on_create":
if "userpassword" in args:
del args["userpassword"]
if "random" in args:
del args["random"]
# if using "random:false" password should not be
# generated.
if not args.get("random", True):
del args["random"]
if "noprivate" in args:
del args["noprivate"]
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
# The nomembers parameter is added to args for the
# api command. But no_members is never part of
# res_find from user-show, therefore this parameter
# needs to be ignored in compare_args_ipa.
if not compare_args_ipa(
ansible_module, args, res_find,
ignore=["no_members"]):
commands.append([name, "user_mod", args])
else:
# Make sure we have a first and last name
if first is None:
ansible_module.fail_json(
msg="First name is needed")
if last is None:
ansible_module.fail_json(
msg="Last name is needed")
smb_attrs = {
k: args[k]
for k in [
"ipanthomedirectory",
"ipanthomedirectorydrive",
"ipantlogonscript",
"ipantprofilepath",
]
if k in args
}
for key in smb_attrs.keys():
del args[key]
commands.append([name, "user_add", args])
if smb_attrs:
commands.append([name, "user_mod", smb_attrs])
# Handle members: principal, manager, certificate and
# certmapdata
if res_find is not None:
# Generate addition and removal lists
manager_add, manager_del = gen_add_del_lists(
manager, res_find.get("manager"))
principal_add, principal_del = gen_add_del_lists(
principal, res_find.get("krbprincipalname"))
# Principals are not returned as utf8 for IPA using
# python2 using user_find, therefore we need to
# convert the principals that we should remove.
principal_del = [to_text(x) for x in principal_del]
certificate_add, certificate_del = gen_add_del_lists(
certificate, res_find.get("usercertificate"))
certmapdata_add, certmapdata_del = gen_add_del_lists(
certmapdata, res_find.get("ipacertmapdata"))
else:
# Use given managers and principals
manager_add = manager or []
manager_del = []
principal_add = principal or []
principal_del = []
certificate_add = certificate or []
certificate_del = []
certmapdata_add = certmapdata or []
certmapdata_del = []
# Remove canonical principal from principal_del
canonical_principal = name + "@" + server_realm
if canonical_principal in principal_del:
principal_del.remove(canonical_principal)
# Add managers
if len(manager_add) > 0:
commands.append([name, "user_add_manager",
{
"user": manager_add,
}])
# Remove managers
if len(manager_del) > 0:
commands.append([name, "user_remove_manager",
{
"user": manager_del,
}])
# Principals need to be added and removed one by one,
# because if entry already exists, the processing of
# the remaining enries is stopped. The same applies to
# the removal of non-existing entries.
# Add principals
if len(principal_add) > 0:
for _principal in principal_add:
commands.append([name, "user_add_principal",
{
"krbprincipalname":
_principal,
}])
# Remove principals
if len(principal_del) > 0:
for _principal in principal_del:
commands.append([name, "user_remove_principal",
{
"krbprincipalname":
_principal,
}])
# Certificates need to be added and removed one by one,
# because if entry already exists, the processing of
# the remaining enries is stopped. The same applies to
# the removal of non-existing entries.
# Add certificates
if len(certificate_add) > 0:
for _certificate in certificate_add:
commands.append([name, "user_add_cert",
{
"usercertificate":
_certificate,
}])
# Remove certificates
if len(certificate_del) > 0:
for _certificate in certificate_del:
commands.append([name, "user_remove_cert",
{
"usercertificate":
_certificate,
}])
# certmapdata need to be added and removed one by one,
# because issuer and subject can only be done one by
# one reliably (https://pagure.io/freeipa/issue/8097)
# Add certmapdata
if len(certmapdata_add) > 0:
for _data in certmapdata_add:
commands.append([name, "user_add_certmapdata",
gen_certmapdata_args(_data)])
# Remove certmapdata
if len(certmapdata_del) > 0:
for _data in certmapdata_del:
commands.append([name, "user_remove_certmapdata",
gen_certmapdata_args(_data)])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No user '%s'" % name)
# Ensure managers are present
if manager is not None and len(manager) > 0:
commands.append([name, "user_add_manager",
{
"user": manager,
}])
# Principals need to be added and removed one by one,
# because if entry already exists, the processing of
# the remaining enries is stopped. The same applies to
# the removal of non-existing entries.
# Ensure principals are present
if principal is not None and len(principal) > 0:
for _principal in principal:
commands.append([name, "user_add_principal",
{
"krbprincipalname":
_principal,
}])
# Certificates need to be added and removed one by one,
# because if entry already exists, the processing of
# the remaining enries is stopped. The same applies to
# the removal of non-existing entries.
# Ensure certificates are present
if certificate is not None and len(certificate) > 0:
for _certificate in certificate:
commands.append([name, "user_add_cert",
{
"usercertificate":
_certificate,
}])
# certmapdata need to be added and removed one by one,
# because issuer and subject can only be done one by
# one reliably (https://pagure.io/freeipa/issue/8097)
# Ensure certmapdata are present
if certmapdata is not None and len(certmapdata) > 0:
for _data in certmapdata:
commands.append([name, "user_add_certmapdata",
gen_certmapdata_args(_data)])
elif state == "absent":
if action == "user":
if res_find is not None:
args = {}
if preserve is not None:
args["preserve"] = preserve
if (
not res_find.get("preserved", False)
or not args.get("preserve", False)
):
commands.append([name, "user_del", args])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No user '%s'" % name)
# Ensure managers are absent
if manager is not None and len(manager) > 0:
commands.append([name, "user_remove_manager",
{
"user": manager,
}])
# Principals need to be added and removed one by one,
# because if entry already exists, the processing of
# the remaining enries is stopped. The same applies to
# the removal of non-existing entries.
# Ensure principals are absent
if principal is not None and len(principal) > 0:
commands.append([name, "user_remove_principal",
{
"krbprincipalname": principal,
}])
# Certificates need to be added and removed one by one,
# because if entry already exists, the processing of
# the remaining enries is stopped. The same applies to
# the removal of non-existing entries.
# Ensure certificates are absent
if certificate is not None and len(certificate) > 0:
for _certificate in certificate:
commands.append([name, "user_remove_cert",
{
"usercertificate":
_certificate,
}])
# certmapdata need to be added and removed one by one,
# because issuer and subject can only be done one by
# one reliably (https://pagure.io/freeipa/issue/8097)
# Ensure certmapdata are absent
if certmapdata is not None and len(certmapdata) > 0:
# Using issuer and subject can only be done one by
# one reliably (https://pagure.io/freeipa/issue/8097)
for _data in certmapdata:
commands.append([name, "user_remove_certmapdata",
gen_certmapdata_args(_data)])
elif state == "undeleted":
if res_find is not None:
if res_find.get("preserved", False):
commands.append([name, "user_undel", {}])
else:
raise ValueError("No user '%s'" % name)
elif state == "enabled":
if res_find is not None:
if res_find["nsaccountlock"]:
commands.append([name, "user_enable", {}])
else:
raise ValueError("No user '%s'" % name)
elif state == "disabled":
if res_find is not None:
if not res_find["nsaccountlock"]:
commands.append([name, "user_disable", {}])
else:
raise ValueError("No user '%s'" % name)
elif state == "unlocked":
if res_find is not None:
commands.append([name, "user_unlock", {}])
else:
raise ValueError("No user '%s'" % name)
elif state == "renamed":
if res_find is None:
ansible_module.fail_json(msg="No user '%s'" % name)
else:
if rename != name:
commands.append([name, 'user_mod', {"rename": rename}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
del user_set
# Execute commands
changed = ansible_module.execute_ipa_commands(
commands, result_handler, exception_handler,
exit_args=exit_args, single_user=users is None)
# Done
ansible_module.exit_json(changed=changed, user=exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/plugins/modules/ipavault.py 0000664 0000000 0000000 00000111513 14600563364 0022736 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipavault
short_description: Manage vaults and secret vaults.
description: Manage vaults and secret vaults. KRA service must be enabled.
extends_documentation_fragment:
- ipamodule_base_docs
options:
name:
description: The vault name
type: list
elements: str
required: true
aliases: ["cn"]
description:
description: The vault description
type: str
required: false
vault_public_key:
description: Base64 encode public key.
required: false
type: str
aliases: ["ipavaultpublickey", "public_key", "new_public_key"]
vault_public_key_file:
description: Path to file with public key.
required: false
type: str
aliases: ["public_key_file", "new_public_key_file"]
private_key:
description: Base64 encode private key.
required: false
type: str
aliases: ["ipavaultprivatekey", "vault_private_key"]
private_key_file:
description: Path to file with private key.
required: false
type: str
aliases: ["vault_private_key_file"]
password:
description: password to be used on symmetric vault.
required: false
type: str
aliases: ["ipavaultpassword", "vault_password", "old_password"]
password_file:
description: file with password to be used on symmetric vault.
required: false
type: str
aliases: ["vault_password_file", "old_password_file"]
new_password:
description: new password to be used on symmetric vault.
required: false
type: str
new_password_file:
description: file with new password to be used on symmetric vault.
required: false
type: str
vault_salt:
description: Vault salt.
required: false
type: str
aliases: ["ipavaultsalt", "salt"]
vault_type:
description: Vault types are based on security level.
type: str
required: false
choices: ["standard", "symmetric", "asymmetric"]
aliases: ["ipavaulttype"]
service:
description: Any service can own one or more service vaults.
required: false
type: str
username:
description: Any user can own one or more user vaults.
required: false
type: str
aliases: ["user"]
shared:
description: Vault is shared.
required: false
type: bool
users:
description: Users that are member of the vault.
required: false
type: list
elements: str
groups:
description: Groups that are member of the vault.
required: false
type: list
elements: str
owners:
description: Users that are owners of the vault.
required: false
type: list
elements: str
aliases: ["ownerusers"]
ownergroups:
description: Groups that are owners of the vault.
required: false
type: list
elements: str
ownerservices:
description: Services that are owners of the vault.
required: false
type: list
elements: str
services:
description: Services that are member of the container.
required: false
type: list
elements: str
data:
description: Data to be stored in the vault.
required: false
type: str
aliases: ["ipavaultdata", "vault_data"]
in:
description: Path to file with data to be stored in the vault.
required: false
type: str
aliases: ["datafile_in"]
out:
description: Path to file to store data retrieved from the vault.
required: false
type: str
aliases: ["datafile_out"]
action:
description: Work on vault or member level.
type: str
default: vault
choices: ["vault", "data", "member"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent", "retrieved"]
author:
- Rafael Guterres Jeffman (@rjeffman)
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure vault symvault is present
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
vault_type: symmetric
password: SomeVAULTpassword
salt: MTIzNDU2Nzg5MAo=
# Ensure group ipausers is a vault member.
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
groups: ipausers
action: member
# Ensure group ipausers is not a vault member.
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
groups: ipausers
action: member
state: absent
# Ensure vault users are present.
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
users:
- user01
- user02
action: member
# Ensure vault users are absent.
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
users:
- user01
- user02
action: member
status: absent
# Ensure user owns vault.
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
action: member
owners: user01
# Ensure user does not own vault.
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
owners: user01
action: member
status: absent
# Ensure data is archived to a symmetric vault
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
password: SomeVAULTpassword
data: >
Data archived.
More data archived.
action: member
# Retrieve data archived from a symmetric vault
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
password: SomeVAULTpassword
state: retrieved
register: result
- debug:
msg: "{{ result.vault.data }}"
# Change password of a symmetric vault
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: admin
old_password: SomeVAULTpassword
new_password: SomeNEWpassword
# Ensure vault symvault is absent
- ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
user: admin
state: absent
# Ensure asymmetric vault is present.
- ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
username: user01
description: An asymmetric vault
vault_type: asymmetric
public_key: |
LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlHZk1BMEdDU3FHU0liM0RRRUJBUVVBQTR
HTkFEQ0JpUUtCZ1FDdGFudjRkK3ptSTZ0T3ova1RXdGowY3AxRAowUENoYy8vR0pJMTUzTi
9CN3UrN0h3SXlRVlZoNUlXZG1UcCtkWXYzd09yeVpPbzYvbHN5eFJaZ2pZRDRwQ3VGCjlxM
295VTFEMnFOZERYeGtSaFFETXBiUEVSWWlHbE1jbzdhN0hIVDk1bGNQbmhObVFkb3VGdHlV
bFBUVS96V1kKZldYWTBOeU1UbUtoeFRseUV3SURBUUFCCi0tLS0tRU5EIFBVQkxJQyBLRVk
tLS0tLQo=
# Ensure data is archived in an asymmetric vault
- ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
username: admin
data: >
Data archived.
More data archived.
action: member
# Retrive data archived in an asymmetric vault, using a private key file.
- ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
username: admin
private_key_file: private.pem
state: retrieved
# Ensure asymmetric vault is absent.
- ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
username: user01
vault_type: asymmetric
state: absent
"""
RETURN = """
vault:
description: Vault dict with archived data.
returned: If state is `retrieved`.
type: dict
contains:
data:
description: The vault data.
returned: always
type: str
"""
import os
from base64 import b64decode
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import IPAAnsibleModule, \
gen_add_del_lists, compare_args_ipa, exit_raw_json, ipalib_errors
def find_vault(module, name, username, service, shared):
_args = {
"all": True,
"cn": name,
}
if username is not None:
_args['username'] = username
elif service is not None:
_args['service'] = service
else:
_args['shared'] = shared
_result = module.ipa_command("vault_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one vault '%s'" % (name))
if len(_result["result"]) == 1:
return _result["result"][0]
return None
def gen_args(
description, username, service, shared, vault_type, salt,
public_key, public_key_file):
_args = {}
vault_type = vault_type or to_text("symmetric")
_args['ipavaulttype'] = vault_type
if description is not None:
_args['description'] = description
if username is not None:
_args['username'] = username
if service is not None:
_args['service'] = service
if shared is not None:
_args['shared'] = shared
if vault_type == "symmetric":
if salt is not None:
_args['ipavaultsalt'] = salt
_args['ipavaultpublickey'] = None
elif vault_type == "asymmetric":
if public_key is not None:
_args['ipavaultpublickey'] = b64decode(public_key.encode('utf-8'))
if public_key_file is not None:
with open(public_key_file, 'r') as keyfile:
keydata = keyfile.read()
_args['ipavaultpublickey'] = keydata.strip().encode('utf-8')
_args['ipavaultsalt'] = None
elif vault_type == "standard":
_args['ipavaultsalt'] = None
_args['ipavaultpublickey'] = None
return _args
def gen_member_args(args, users, groups, services):
remove = ['ipavaulttype', 'description', 'ipavaultpublickey',
'ipavaultsalt']
_args = {k: v for k, v in args.items() if k not in remove}
if any([users, groups, services]):
if users is not None:
_args['user'] = users
if groups is not None:
_args['group'] = groups
if services is not None:
_args['services'] = services
return _args
return None
def data_storage_args(vault_type, args, data, password, password_file,
private_key, private_key_file, datafile_in,
datafile_out):
remove = ['ipavaulttype', 'description', 'ipavaultpublickey',
'ipavaultsalt']
_args = {k: v for k, v in args.items() if k not in remove}
if 'username' in args:
_args['username'] = args['username']
if 'service' in args:
_args['service'] = args['service']
if 'shared' in args:
_args['shared'] = args['shared']
if vault_type is None or vault_type == "symmetric":
if password is not None:
_args['password'] = password
if password_file is not None:
_args['password_file'] = password_file
if vault_type == "asymmetric":
if private_key is not None:
_args['private_key'] = private_key
if private_key_file is not None:
_args['private_key_file'] = private_key_file
if datafile_in is not None:
_args['in'] = datafile_in
else:
if data is None:
_args['data'] = b''
else:
_args['data'] = data.encode('utf-8')
if datafile_out is not None:
_args['out'] = datafile_out
return _args
def check_parameters( # pylint: disable=unused-argument
module, state, action, description, username, service, shared, users,
groups, services, owners, ownergroups, ownerservices, vault_type, salt,
password, password_file, public_key, public_key_file, private_key,
private_key_file, vault_data, datafile_in, datafile_out, new_password,
new_password_file):
if module.params_get("ipaapi_context") == "server":
module.fail_json(
msg="Context 'server' for ipavault not yet supported."
)
invalid = []
if state == "present":
invalid = ['datafile_out']
if all([password, password_file]) \
or all([new_password, new_password_file]):
module.fail_json(msg="Password specified multiple times.")
if any([new_password, new_password_file]) \
and not any([password, password_file]):
module.fail_json(
msg="Either `password` or `password_file` must be provided to "
"change symmetric vault password.")
if action == "member":
invalid.extend(['description', 'vault_type'])
elif state == "absent":
invalid = ['description', 'salt', 'vault_type', 'private_key',
'private_key_file', 'datafile_in', 'datafile_out',
'vault_data', 'new_password', 'new_password_file']
if action == "vault":
invalid.extend(['users', 'groups', 'services', 'owners',
'ownergroups', 'ownerservices', 'password',
'password_file', 'public_key', 'public_key_file'])
elif state == "retrieved":
invalid = ['description', 'salt', 'datafile_in', 'users', 'groups',
'owners', 'ownergroups', 'public_key', 'public_key_file',
'vault_data', 'new_password', 'new_password_file']
if action == 'member':
module.fail_json(
msg="State `retrieved` do not support action `member`.")
module.params_fail_used_invalid(invalid, state, action)
def check_encryption_params( # pylint: disable=unused-argument
module, state, action, vault_type, salt, password, password_file,
public_key, public_key_file, private_key, private_key_file, vault_data,
datafile_in, datafile_out, new_password, new_password_file, res_find):
"""Check parameters used for (de)vault data encryption."""
vault_type_invalid = []
existing_type = None
if res_find:
existing_type = res_find["ipavaulttype"][0]
if vault_type is None and res_find is not None:
vault_type = res_find['ipavaulttype']
if isinstance(vault_type, (tuple, list)):
vault_type = vault_type[0]
if vault_type == "standard":
vault_type_invalid = ['public_key', 'public_key_file', 'password',
'password_file', 'salt', 'new_password',
'new_password_file']
if vault_type is None or vault_type == "symmetric":
vault_type_invalid = ['public_key', 'public_key_file',
'private_key', 'private_key_file']
if password is None and password_file is None and action != 'member':
module.fail_json(
msg="Symmetric vault requires password or password_file "
"to store data or change `salt`.")
if any([new_password, new_password_file]) and res_find is None:
module.fail_json(
msg="Cannot modify password of inexistent vault.")
if (
salt is not None
and not (
any([password, password_file])
and any([new_password, new_password_file])
)
):
module.fail_json(
msg="Vault `salt` can only change when changing the password.")
if vault_type == "asymmetric":
vault_type_invalid = [
'password', 'password_file', 'new_password', 'new_password_file'
]
if not any([public_key, public_key_file]) and res_find is None:
module.fail_json(
msg="Assymmetric vault requires public_key "
"or public_key_file to store data.")
valid_fields = []
if existing_type == "symmetric":
valid_fields = [
'password', 'password_file', 'new_password', 'new_password_file',
'salt'
]
if existing_type == "asymmetric":
valid_fields = [
'public_key', 'public_key_file', 'private_key', 'private_key_file'
]
check_fields = [f for f in vault_type_invalid if f not in valid_fields]
for param in check_fields:
if vars()[param] is not None:
module.fail_json(
msg="Argument '%s' cannot be used with vault type '%s'" %
(param, vault_type or 'symmetric'))
def get_stored_data(module, res_find, args):
"""Retrieve data stored in the vault."""
# prepare arguments to retrieve data.
name = res_find["cn"][0]
copy_args = []
if res_find['ipavaulttype'][0] == "symmetric":
copy_args = ["password", "password_file"]
if res_find['ipavaulttype'][0] == "asymmetric":
copy_args = ["private_key", "private_key_file"]
pwdargs = {arg: args[arg] for arg in copy_args if arg in args}
# retrieve vault stored data
try:
result = module.ipa_command('vault_retrieve', name, pwdargs)
except ipalib_errors.NotFound:
return None
return result['result'].get('data')
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# generalgroups
name=dict(type="list", elements="str", aliases=["cn"],
required=True),
description=dict(required=False, type="str", default=None),
vault_type=dict(type="str", aliases=["ipavaulttype"],
default=None, required=False,
choices=["standard", "symmetric", "asymmetric"]),
vault_public_key=dict(type="str", required=False, default=None,
aliases=['ipavaultpublickey', 'public_key',
'new_public_key']),
vault_public_key_file=dict(type="str", required=False,
default=None,
aliases=['public_key_file',
'new_public_key_file']),
vault_private_key=dict(
type="str", required=False, default=None, no_log=True,
aliases=['ipavaultprivatekey', 'private_key']),
vault_private_key_file=dict(type="str", required=False,
default=None,
aliases=['private_key_file']),
vault_salt=dict(type="str", required=False, default=None,
aliases=['ipavaultsalt', 'salt']),
username=dict(type="str", required=False, default=None,
aliases=['user']),
service=dict(type="str", required=False, default=None),
shared=dict(type="bool", required=False, default=None),
users=dict(required=False, type="list", elements="str",
default=None),
groups=dict(required=False, type="list", elements="str",
default=None),
services=dict(required=False, type="list", elements="str",
default=None),
owners=dict(required=False, type="list", elements="str",
default=None,
aliases=['ownerusers']),
ownergroups=dict(required=False, type="list", elements="str",
default=None),
ownerservices=dict(required=False, type="list", elements="str",
default=None),
vault_data=dict(type="str", required=False, default=None,
no_log=True, aliases=['ipavaultdata', 'data']),
datafile_in=dict(type="str", required=False, default=None,
aliases=['in']),
datafile_out=dict(type="str", required=False, default=None,
aliases=['out']),
vault_password=dict(type="str", required=False, default=None,
no_log=True,
aliases=['ipavaultpassword', 'password',
"old_password"]),
vault_password_file=dict(type="str", required=False, default=None,
no_log=False,
aliases=[
'password_file', "old_password_file"
]),
new_password=dict(type="str", required=False, default=None,
no_log=True),
new_password_file=dict(type="str", required=False, default=None,
no_log=False),
# state
action=dict(type="str", default="vault",
choices=["vault", "data", "member"]),
state=dict(type="str", default="present",
choices=["present", "absent", "retrieved"]),
),
supports_check_mode=True,
mutually_exclusive=[['username', 'service', 'shared'],
['datafile_in', 'vault_data'],
['new_password', 'new_password_file'],
['vault_password', 'vault_password_file'],
['vault_public_key', 'vault_public_key_file']],
)
ansible_module._ansible_debug = True
# general
names = ansible_module.params_get("name")
# present
description = ansible_module.params_get("description")
username = ansible_module.params_get("username")
service = ansible_module.params_get("service")
shared = ansible_module.params_get("shared")
users = ansible_module.params_get("users")
groups = ansible_module.params_get("groups")
services = ansible_module.params_get("services")
owners = ansible_module.params_get("owners")
ownergroups = ansible_module.params_get("ownergroups")
ownerservices = ansible_module.params_get("ownerservices")
vault_type = ansible_module.params_get("vault_type")
salt = ansible_module.params_get("vault_salt")
password = ansible_module.params_get("vault_password")
password_file = ansible_module.params_get("vault_password_file")
new_password = ansible_module.params_get("new_password")
new_password_file = ansible_module.params_get("new_password_file")
public_key = ansible_module.params_get("vault_public_key")
public_key_file = ansible_module.params_get("vault_public_key_file")
private_key = ansible_module.params_get("vault_private_key")
private_key_file = ansible_module.params_get("vault_private_key_file")
vault_data = ansible_module.params_get("vault_data")
datafile_in = ansible_module.params_get("datafile_in")
datafile_out = ansible_module.params_get("datafile_out")
action = ansible_module.params_get("action")
state = ansible_module.params_get("state")
# Check parameters
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one vault can be added at a time.")
elif state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
elif state == "retrieved":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one vault can be retrieved at a time.")
else:
ansible_module.fail_json(msg="Invalid state '%s'" % state)
check_parameters(ansible_module, state, action, description, username,
service, shared, users, groups, services, owners,
ownergroups, ownerservices, vault_type, salt, password,
password_file, public_key, public_key_file, private_key,
private_key_file, vault_data, datafile_in, datafile_out,
new_password, new_password_file)
# Init
changed = False
exit_args = {}
with ansible_module.ipa_connect(context="client") as ccache_name:
if ccache_name is not None:
os.environ["KRB5CCNAME"] = ccache_name
commands = []
for name in names:
# Make sure vault exists
res_find = find_vault(
ansible_module, name, username, service, shared)
# Set default vault_type if needed.
res_type = res_find.get('ipavaulttype')[0] if res_find else None
if vault_type is None:
vault_type = res_type if res_find is not None else u"symmetric"
# Generate args
args = gen_args(description, username, service, shared, vault_type,
salt, public_key, public_key_file)
pwdargs = None
# Create command
if state == "present":
# verify data encription args
check_encryption_params(
ansible_module, state, action, vault_type, salt, password,
password_file, public_key, public_key_file, private_key,
private_key_file, vault_data, datafile_in, datafile_out,
new_password, new_password_file, res_find)
change_passwd = any([
new_password, new_password_file,
(private_key or private_key_file) and
(public_key or public_key_file)
])
if action == "vault":
# Found the vault
if res_find is not None:
arg_type = args.get("ipavaulttype")
modified = not compare_args_ipa(ansible_module,
args, res_find)
if arg_type != res_type or change_passwd:
stargs = data_storage_args(
res_type, args, vault_data, password,
password_file, private_key,
private_key_file, datafile_in,
datafile_out)
stored = get_stored_data(
ansible_module, res_find, stargs
)
if stored:
vault_data = \
(stored or b"").decode("utf-8")
remove_attrs = {
"symmetric": ["private_key", "public_key"],
"asymmetric": ["password", "ipavaultsalt"],
"standard": [
"private_key", "public_key",
"password", "ipavaultsalt"
],
}
for attr in remove_attrs.get(arg_type, []):
if attr in args:
del args[attr]
if vault_type == 'symmetric':
if 'ipavaultsalt' not in args:
args['ipavaultsalt'] = os.urandom(32)
else:
args['ipavaultsalt'] = b''
if modified:
commands.append([name, "vault_mod_internal", args])
else:
if vault_type == 'symmetric' \
and 'ipavaultsalt' not in args:
args['ipavaultsalt'] = os.urandom(32)
commands.append([name, "vault_add_internal", args])
if vault_type != 'standard' and vault_data is None:
vault_data = ''
# Set res_find to empty dict for next steps
res_find = {}
# Generate adittion and removal lists
user_add, user_del = \
gen_add_del_lists(users,
res_find.get('member_user', []))
group_add, group_del = \
gen_add_del_lists(groups,
res_find.get('member_group', []))
service_add, service_del = \
gen_add_del_lists(services,
res_find.get('member_service', []))
owner_add, owner_del = \
gen_add_del_lists(owners,
res_find.get('owner_user', []))
ownergroups_add, ownergroups_del = \
gen_add_del_lists(ownergroups,
res_find.get('owner_group', []))
ownerservice_add, ownerservice_del = \
gen_add_del_lists(ownerservices,
res_find.get('owner_service', []))
# Add users and groups
user_add_args = gen_member_args(args, user_add,
group_add, service_add)
if user_add_args is not None:
commands.append(
[name, 'vault_add_member', user_add_args])
# Remove users and groups
user_del_args = gen_member_args(args, user_del,
group_del, service_del)
if user_del_args is not None:
commands.append(
[name, 'vault_remove_member', user_del_args])
# Add owner users and groups
owner_add_args = gen_member_args(
args, owner_add, ownergroups_add, ownerservice_add)
if owner_add_args is not None:
commands.append(
[name, 'vault_add_owner', owner_add_args])
# Remove owner users and groups
owner_del_args = gen_member_args(
args, owner_del, ownergroups_del, ownerservice_del)
if owner_del_args is not None:
commands.append(
[name, 'vault_remove_owner', owner_del_args])
elif action in "member":
# Add users and groups
if any([users, groups, services]):
user_args = gen_member_args(args, users, groups,
services)
commands.append([name, 'vault_add_member', user_args])
if any([owners, ownergroups, ownerservices]):
owner_args = gen_member_args(args, owners, ownergroups,
ownerservices)
commands.append([name, 'vault_add_owner', owner_args])
if any([vault_data, datafile_in]):
if change_passwd:
pwdargs = data_storage_args(
vault_type, args, vault_data, new_password,
new_password_file, private_key, private_key_file,
datafile_in, datafile_out)
else:
pwdargs = data_storage_args(
vault_type, args, vault_data, password,
password_file, private_key, private_key_file,
datafile_in, datafile_out)
pwdargs['override_password'] = True
pwdargs.pop("private_key", None)
pwdargs.pop("private_key_file", None)
commands.append([name, "vault_archive", pwdargs])
elif state == "retrieved":
if res_find is None:
ansible_module.fail_json(
msg="Vault `%s` not found to retrieve data." % name)
# verify data encription args
check_encryption_params(
ansible_module, state, action, vault_type, salt, password,
password_file, public_key, public_key_file, private_key,
private_key_file, vault_data, datafile_in, datafile_out,
new_password, new_password_file, res_find)
pwdargs = data_storage_args(
res_find["ipavaulttype"][0], args, vault_data, password,
password_file, private_key, private_key_file, datafile_in,
datafile_out)
if 'data' in pwdargs:
del pwdargs['data']
commands.append([name, "vault_retrieve", pwdargs])
elif state == "absent":
if 'ipavaulttype' in args:
del args['ipavaulttype']
if action == "vault":
if res_find is not None:
remove = ['ipavaultsalt', 'ipavaultpublickey']
args = {
k: v for k, v in args.items() if k not in remove
}
commands.append([name, "vault_del", args])
elif action == "member":
# remove users and groups
if any([users, groups, services]):
user_args = gen_member_args(
args, users, groups, services)
commands.append(
[name, 'vault_remove_member', user_args])
if any([owners, ownergroups, ownerservices]):
owner_args = gen_member_args(
args, owners, ownergroups, ownerservices)
commands.append(
[name, 'vault_remove_owner', owner_args])
else:
ansible_module.fail_json(
msg="Invalid action '%s' for state '%s'" %
(action, state))
else:
ansible_module.fail_json(msg="Unknown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands
errors = []
for name, command, args in commands:
try:
result = ansible_module.ipa_command(command, name, args)
if command == 'vault_archive':
changed = 'Archived data into' in result['summary']
elif command == 'vault_retrieve':
if 'result' not in result:
# pylint: disable=W0012,broad-exception-raised
raise Exception("No result obtained.")
if "data" in result["result"]:
data_return = exit_args.setdefault("vault", {})
data_return["data"] = result["result"]["data"]
else:
if not datafile_out:
# pylint: disable=W0012,broad-exception-raised
raise Exception("No data retrieved.")
changed = False
else:
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except ipalib_errors.EmptyModlist:
result = {}
except Exception as exception: # pylint: disable=broad-except
ansible_module.fail_json(
msg="%s: %s: %s" % (command, name, str(exception)))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
# Done
# exit_raw_json is a replacement for ansible_module.exit_json that
# does not mask the output.
exit_raw_json(ansible_module, changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/pytest.ini 0000664 0000000 0000000 00000000211 14600563364 0017427 0 ustar 00root root 0000000 0000000 [pytest]
python_files = test_*.py
junit_family = xunit1
markers=
source_order: mark test as order bound
playbook: playbook tests
ansible-freeipa-master/requirements-dev.txt 0000664 0000000 0000000 00000000254 14600563364 0021445 0 ustar 00root root 0000000 0000000 -r requirements-tests.txt
ipdb==0.13.4
pre-commit==2.20.0
flake8==6.0.0
flake8-bugbear
pylint==2.17.2
wrapt==1.14.1
pydocstyle==6.3.0
yamllint==1.32.0
ansible-lint >= 6.22
ansible-freeipa-master/requirements-docker.yml 0000664 0000000 0000000 00000000054 14600563364 0022116 0 ustar 00root root 0000000 0000000 ---
collections:
- name: community.docker
ansible-freeipa-master/requirements-podman.yml 0000664 0000000 0000000 00000000055 14600563364 0022126 0 ustar 00root root 0000000 0000000 ---
collections:
- name: containers.podman
ansible-freeipa-master/requirements-tests.txt 0000664 0000000 0000000 00000000251 14600563364 0022026 0 ustar 00root root 0000000 0000000 -r requirements.txt
pytest==7.1.3
pytest-sourceorder==0.6.0
pytest-split>=0.8.0
pytest-custom_exit_code>=0.3.0
pytest-testinfra==6.8.0
pytest-randomly==3.12.0
pyyaml>=3
ansible-freeipa-master/requirements.txt 0000664 0000000 0000000 00000000000 14600563364 0020656 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ 0000775 0000000 0000000 00000000000 14600563364 0016530 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipabackup/ 0000775 0000000 0000000 00000000000 14600563364 0020467 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipabackup/README.md 0000664 0000000 0000000 00000023425 14600563364 0021754 0 ustar 00root root 0000000 0000000 ipabackup role
==============
Description
-----------
This role allows to backup an IPA server, to copy a backup from the server to the controller, to copy all backups from the server to the controller, to remove a backup from the server, to remove all backups from the server, to restore an IPA server locally and from the controller and also to copy a backup from the controller to the server.
**Note**: The ansible playbooks and role require a configured ansible environment where the ansible nodes are reachable and are properly set up to have an IP address and a working package manager.
Features
--------
* Server backup
* Server backup to controller
* Copy backup from server to controller
* Copy all backups from server to controller
* Remove backup from the server
* Remove all backups from the server
* Server restore from server local backup.
* Server restore from controller.
* Copy a backup from the controller to the server.
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.5 and up are supported by the backup role.
Supported Distributions
-----------------------
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
* Ubuntu 16.04 and 18.04
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
* Supported distribution (needed for package installation only, see above)
Usage
=====
Example inventory file with fixed domain and realm, setting up of the DNS server and using forwarders from /etc/resolv.conf:
```ini
[ipaserver]
ipaserver.example.com
```
Example playbook to create a backup on the IPA server locally:
```yaml
---
- name: Playbook to backup IPA server
hosts: ipaserver
become: true
roles:
- role: ipabackup
state: present
```
Example playbook to create a backup of the IPA server that is transferred to the controller using the server name as prefix for the backup and removed on the server:
```yaml
---
- name: Playbook to backup IPA server to controller
hosts: ipaserver
become: true
vars:
ipabackup_to_controller: yes
# ipabackup_keep_on_server: yes
roles:
- role: ipabackup
state: present
```
Example playbook to create a backup of the IPA server that is transferred to the controller using the server name as prefix for the backup and kept on the server:
```yaml
---
- name: Playbook to backup IPA server to controller
hosts: ipaserver
become: true
vars:
ipabackup_to_controller: yes
ipabackup_keep_on_server: yes
roles:
- role: ipabackup
state: present
```
Copy backup `ipa-full-2020-10-01-10-00-00` from server to controller:
```yaml
---
- name: Playbook to copy backup from IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name: ipa-full-2020-10-01-10-00-00
ipabackup_to_controller: yes
roles:
- role: ipabackup
state: copied
```
Copy backups `ipa-full-2020-10-01-10-00-00` and `ipa-full-2020-10-02-10-00-00` from server to controller:
```yaml
---
- name: Playbook to copy backup from IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name:
- ipa-full-2020-10-01-10-00-00
- ipa-full-2020-10-02-10-00-00
ipabackup_to_controller: yes
roles:
- role: ipabackup
state: copied
```
Copy all backups from server to controller that are following the backup naming scheme:
```yaml
---
- name: Playbook to copy all backups from IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name: all
ipabackup_to_controller: yes
roles:
- role: ipabackup
state: copied
```
Remove backup `ipa-full-2020-10-01-10-00-00` from server:
```yaml
---
- name: Playbook to remove backup from IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name: ipa-full-2020-10-01-10-00-00
roles:
- role: ipabackup
state: absent
```
Remove backups `ipa-full-2020-10-01-10-00-00` and `ipa-full-2020-10-02-10-00-00` from server:
```yaml
---
- name: Playbook to remove backup from IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name:
- ipa-full-2020-10-01-10-00-00
- ipa-full-2020-10-02-10-00-00
roles:
- role: ipabackup
state: absent
```
Remove all backups from server that are following the backup naming scheme:
```yaml
---
- name: Playbook to remove all backups from IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name: all
roles:
- role: ipabackup
state: absent
```
Example playbook to restore an IPA server locally:
```yaml
---
- name: Playbook to restore an IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name: ipa-full-2020-10-22-11-11-44
ipabackup_password: SomeDMpassword
roles:
- role: ipabackup
state: restored
```
Example playbook to restore IPA server from controller:
```yaml
---
- name: Playbook to restore IPA server from controller
hosts: ipaserver
become: true
vars:
ipabackup_name: ipaserver.test.local_ipa-full-2020-10-22-11-11-44
ipabackup_password: SomeDMpassword
ipabackup_from_controller: yes
roles:
- role: ipabackup
state: restored
```
Example playbook to copy a backup from controller to the IPA server:
```yaml
---
- name: Playbook to copy a backup from controller to the IPA server
hosts: ipaserver
become: true
vars:
ipabackup_name: ipaserver.test.local_ipa-full-2020-10-22-11-11-44
ipabackup_from_controller: yes
roles:
- role: ipabackup
state: copied
```
Playbooks
=========
The example playbooks to do the backup, copy a backup and also to remove a backup, also to do the restore, copy a backup to the server are part of the repository in the playbooks folder.
```
backup-server.yml
backup-server-to-controller.yml
copy-all-backups-from-server.yml
copy-backup-from-server.yml
remove-all-backups-from-server.yml
remove-backup-from-server.yml
restore-server.yml
restore-server-from-controller.yml
copy-backup-from-controller.yml
```
Please remember to link or copy the playbooks to the base directory of ansible-freeipa if you want to use the roles within the source archive.
Variables
=========
Base Variables
--------------
Variable | Description | Required
-------- | ----------- | --------
ipabackup_backend | The backend to restore within the instance or instances, str | no
ipabackup_data | Backup only the data with `state: present` and restore only the data with `state: restored`, bool (default: `no`) | no
ipabackup_disable_role_check | Perform the backup even if this host does not have all the roles used in the cluster. This is not recommended, bool (default: `no`) | no
ipabackup_gpg | Encrypt the backup, bool (default: `no`) | no
ipabackup_gpg_keyring | Full path to the GPG keyring without the file extension, only for GPG 1 and up to IPA 4.6 str | no
ipabackup_instance | The 389-ds instance to restore (defaults to all found), str | no
ipabackup_log_file | Log to the given file on server for `state: present` and `state: restored` only, string | no
ipabackup_logs | Include log files in backup, bool (default: `no`) | no
ipabackup_no_logs | Do not restore log files from the backup, bool (default: `no`) | no
ipabackup_online | Perform the LDAP backups online for data only with `state: present` and perform the LDAP restore online for data only with `state: restored`. If `ipabackup_data` is not set it will automatically be enabled. bool (default: `no`) | no
ipabackup_password | The diretory manager password needed for restoring a backup with `state: restored`, str | no
state | `present` to make a new backup, `absent` to remove a backup and `copied` to copy a backup from the server to the controller or from the controller to the server, `restored` to restore a backup. string (default: `present`) | yes
Special Variables
-----------------
Variable | Description | Required
-------- | ----------- | --------
ipabackup_name | The IPA backup name(s). Only for removal of server local backup(s) with `state: absent`, to copy server local backup(s) to the controller with `state: copied` and `ipabackup_from_server` set, to copy a backup from the controller to the server with `state: copied` and `ipabackup_from_controller` set or to restore a backup with `state: restored` either locally on the server of from the controller with `ipabackup_from_controller` set. If `all` is used all available backups are copied or removed that are following the backup naming scheme. string list | no
ipabackup_keep_on_server | Keep local copy of backup on server with `state: present` and `ipabackup_to_controller`, bool (default: `no`) | no
ipabackup_to_controller | Copy backup to controller, prefixes backup with node name, remove backup on server if `ipabackup_keep_on_server` is not set, bool (default: `no`) | no
ipabackup_controller_path | Pre existing path on controller to store the backup in with `state: present`, path on the controller to copy the backup from with `state: copied` and `ipabackup_from_controller` set also for the restore with `state: restored` and `ipabackup_from_controller` set. If this is not set, the current working dir is used. string | no
ipabackup_name_prefix | Set prefix to use for backup directory on controller with `state: present` or `state: copied` and `ipabackup_to_controller` set, The default is the server FQDN, string | no
ipabackup_from_controller | Copy backup from controller to server, restore if `state: restored`, copy backup to server if `state: copied`, bool (default: `no`) | no
ipabackup_install_packages | Install needed packages to be able to apply the backup with `state: restored`, bool (default: `yes`) | no
ipabackup_firewalld_zone | The value defines the firewall zone that will be used with `state: restored`. This needs to be an existing runtime and permanent zone, bool (default: `no`) | no
ipabackup_setup_firewalld | The value defines if the needed services will automatically be opened in the firewall managed by firewalld with `state: restored`, bool (default: `yes`) | no
Authors
=======
Thomas Woerner
ansible-freeipa-master/roles/ipabackup/defaults/ 0000775 0000000 0000000 00000000000 14600563364 0022276 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipabackup/defaults/main.yml 0000664 0000000 0000000 00000000516 14600563364 0023747 0 ustar 00root root 0000000 0000000 ---
# defaults file for ipabackup
ipabackup_gpg: no
ipabackup_data: no
ipabackup_logs: no
ipabackup_online: no
ipabackup_disable_role_check: no
ipabackup_no_logs: no
### special ###
ipabackup_keep_on_server: no
ipabackup_to_controller: no
ipabackup_from_controller: no
ipabackup_install_packages: yes
ipabackup_setup_firewalld: yes
ansible-freeipa-master/roles/ipabackup/library/ 0000775 0000000 0000000 00000000000 14600563364 0022133 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipabackup/library/ipabackup_get_backup_dir.py 0000664 0000000 0000000 00000003751 14600563364 0027474 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2021-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipabackup_get_backup_dir
short_description:
Get IPA_BACKUP_DIR from ipaplatform
description:
Get IPA_BACKUP_DIR from ipaplatform
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
# Get IPA_BACKUP_DIR from ipaplatform
- name: Get IPA_BACKUP_DIR from ipaplatform
ipabackup_get_backup_dir:
register: result
'''
RETURN = '''
backup_dir:
description: IPA_BACKUP_DIR from ipaplatform
returned: always
type: str
'''
from ansible.module_utils.basic import AnsibleModule
try:
from ipaplatform.paths import paths
except ImportError as _err:
MODULE_IMPORT_ERROR = str(_err)
paths = None
else:
MODULE_IMPORT_ERROR = None
def main():
module = AnsibleModule(
argument_spec={},
supports_check_mode=True,
)
if MODULE_IMPORT_ERROR is not None:
module.fail_json(msg=MODULE_IMPORT_ERROR)
module.exit_json(changed=False,
backup_dir=paths.IPA_BACKUP_DIR)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipabackup/meta/ 0000775 0000000 0000000 00000000000 14600563364 0021415 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipabackup/meta/main.yml 0000664 0000000 0000000 00000000530 14600563364 0023062 0 ustar 00root root 0000000 0000000 ---
dependencies: []
galaxy_info:
author: Thomas Woerner
description: A role to backup and restore an IPA server
company: Red Hat, Inc
license: GPLv3
min_ansible_version: "2.13"
platforms:
- name: Fedora
versions:
- all
- name: EL
versions:
- "7"
- "8"
galaxy_tags:
- identity
- ipa
- freeipa
ansible-freeipa-master/roles/ipabackup/tasks/ 0000775 0000000 0000000 00000000000 14600563364 0021614 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipabackup/tasks/backup.yml 0000664 0000000 0000000 00000002733 14600563364 0023611 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipabackup
- name: Create backup
ansible.builtin.shell: >
ipa-backup
{{ "--gpg" if ipabackup_gpg | bool else "" }}
{{ "--gpg-keyring=" + ipabackup_gpg_keyring if ipabackup_gpg_keyring is defined else "" }}
{{ "--data" if ipabackup_data | bool else "" }}
{{ "--logs" if ipabackup_logs | bool else "" }}
{{ "--online" if ipabackup_online | bool else "" }}
{{ "--disable-role-check" if ipabackup_disable_role_check | bool else "" }}
{{ "--log-file=" + ipabackup_log_file if ipabackup_log_file is defined else "" }}
register: result_ipabackup
- name: Handle backup
when: ipabackup_to_controller
block:
- name: Get ipabackup_item from stderr or stdout output
ansible.builtin.set_fact:
ipabackup_item: "{{ item | regex_search('\n.*/([^\n]+)','\\1') | first }}"
when: item.find("Backed up to "+ipabackup_dir+"/") > 0
with_items:
- "{{ result_ipabackup.stderr }}"
- "{{ result_ipabackup.stdout }}"
loop_control:
label: ""
- name: Fail on missing ipabackup_item
ansible.builtin.fail:
msg: "Failed to get ipabackup_item"
when: ipabackup_item is not defined
- name: Copy backup to controller
ansible.builtin.include_tasks: "{{ role_path }}/tasks/copy_backup_from_server.yml"
when: state|default("present") == "present"
- name: Remove backup on server
ansible.builtin.include_tasks: "{{ role_path }}/tasks/remove_backup_from_server.yml"
when: not ipabackup_keep_on_server
ansible-freeipa-master/roles/ipabackup/tasks/copy_backup_from_server.yml 0000664 0000000 0000000 00000003040 14600563364 0027244 0 ustar 00root root 0000000 0000000 ---
- name: Fail on invalid ipabackup_item
ansible.builtin.fail:
msg: "ipabackup_item {{ ipabackup_item }} is not valid"
when: ipabackup_item is not defined or
ipabackup_item | length < 1 or
(ipabackup_item.find("ipa-full-") == -1 and
ipabackup_item.find("ipa-data-") == -1)
- name: Set controller destination directory
ansible.builtin.set_fact:
__derived_controller_dir:
"{{ ipabackup_controller_path | default(lookup('env', 'PWD')) }}/{{
ipabackup_name_prefix | default(ansible_facts['fqdn']) }}_{{
ipabackup_item }}/"
- name: Stat backup on server
ansible.builtin.stat:
path: "{{ ipabackup_dir }}/{{ ipabackup_item }}"
register: result_backup_stat
- name: Fail on missing backup directory
ansible.builtin.fail:
msg: "Unable to find backup {{ ipabackup_item }}"
when: result_backup_stat.stat.isdir is not defined
- name: Get backup files to copy for "{{ ipabackup_item }}"
ansible.builtin.shell:
find . -type f | cut -d"/" -f 2
args:
chdir: "{{ ipabackup_dir }}/{{ ipabackup_item }}"
register: result_find_backup_files
- name: Copy server backup files to controller
ansible.builtin.fetch:
flat: yes
src: "{{ ipabackup_dir }}/{{ ipabackup_item }}/{{ item }}"
dest: "{{ __derived_controller_dir }}"
with_items:
- "{{ result_find_backup_files.stdout_lines }}"
- name: Fix file modes for backup on controller
ansible.builtin.file:
dest: "{{ __derived_controller_dir }}"
mode: u=rwX,go=
recurse: yes
delegate_to: localhost
become: no
ansible-freeipa-master/roles/ipabackup/tasks/copy_backup_to_server.yml 0000664 0000000 0000000 00000002650 14600563364 0026731 0 ustar 00root root 0000000 0000000 ---
- name: Fail on invalid ipabackup_name
ansible.builtin.fail:
msg: "ipabackup_name {{ ipabackup_name }} is not valid"
when: ipabackup_name is not defined or
ipabackup_name | length < 1 or
(ipabackup_name.find("ipa-full-") == -1 and
ipabackup_name.find("ipa-data-") == -1)
- name: Set controller source directory
ansible.builtin.set_fact:
__derived_controller_dir:
"{{ ipabackup_controller_path | default(lookup('env', 'PWD')) }}"
- name: Set ipabackup_item
ansible.builtin.set_fact:
ipabackup_item:
"{{ ipabackup_name | regex_search('.*_(ipa-.+)', '\\1') | first }}"
when: "'_ipa-' in ipabackup_name"
- name: Set ipabackup_item
ansible.builtin.set_fact:
ipabackup_item: "{{ ipabackup_name }}"
when: "'_ipa-' not in ipabackup_name"
- name: Stat backup to copy
ansible.builtin.stat:
path: "{{ __derived_controller_dir }}/{{ ipabackup_name }}"
register: result_backup_stat
delegate_to: localhost
become: no
- name: Fail on missing backup to copy
ansible.builtin.fail:
msg: "Unable to find backup {{ ipabackup_name }}"
when: result_backup_stat.stat.isdir is not defined
- name: Copy backup files to server for "{{ ipabackup_item }}"
ansible.builtin.copy:
src: "{{ __derived_controller_dir }}/{{ ipabackup_name }}/"
dest: "{{ ipabackup_dir }}/{{ ipabackup_item }}"
owner: root
group: root
mode: u=rw,go=r
directory_mode: u=rwx,go=
ansible-freeipa-master/roles/ipabackup/tasks/get_ipabackup_dir.yml 0000664 0000000 0000000 00000000366 14600563364 0026000 0 ustar 00root root 0000000 0000000 ---
- name: Get IPA_BACKUP_DIR from ipaplatform
ipabackup_get_backup_dir:
register: result_ipabackup_get_backup_dir
- name: Set IPA backup dir
ansible.builtin.set_fact:
ipabackup_dir: "{{ result_ipabackup_get_backup_dir.backup_dir }}"
ansible-freeipa-master/roles/ipabackup/tasks/main.yml 0000664 0000000 0000000 00000012351 14600563364 0023265 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipabackup
- name: Check for empty vars
ansible.builtin.fail:
msg: "Variable {{ item }} is empty"
when: "item in vars and not vars[item]"
with_items: "{{ ipabackup_empty_var_checks }}"
vars:
ipabackup_empty_var_checks:
- ipabackup_backend
- ipabackup_gpg_keyring
- ipabackup_instance
- ipabackup_log_file
- ipabackup_password
- ipabackup_name
- ipabackup_controller_path
- ipabackup_name_prefix
- ipabackup_firewalld_zone
- name: Set ipabackup_data if ipabackup_data is not set but ipabackup_online is
ansible.builtin.set_fact:
ipabackup_data: yes
when: ipabackup_online | bool and not ipabackup_data | bool
- name: Fail if ipabackup_from_controller and ipabackup_to_controller are set
ansible.builtin.fail:
msg: "ipabackup_from_controller and ipabackup_to_controller are set"
when: ipabackup_from_controller | bool and ipabackup_to_controller | bool
- name: Fail for given ipabackup_name if state is not copied, restored or absent
ansible.builtin.fail:
msg: "ipabackup_name is given and state is not copied, restored or absent"
when: state is not defined or
(state != "copied" and state != "restored" and state != "absent") and
ipabackup_name is defined
- name: Get ipabackup_dir from IPA installation
ansible.builtin.include_tasks: "{{ role_path }}/tasks/get_ipabackup_dir.yml"
- name: Backup IPA server
ansible.builtin.include_tasks: "{{ role_path }}/tasks/backup.yml"
when: state|default("present") == "present"
- name: Fail on missing ipabackup_name
ansible.builtin.fail:
msg: "ipabackup_name is not set"
when: (ipabackup_name is not defined or not ipabackup_name) and
state is defined and
(state == "copied" or state == "restored" or state == "absent")
- name: Get all backup names for copy to controller
when: state is defined and
((state == "copied" and ipabackup_to_controller) or
state == "absent") and
ipabackup_name is defined and ipabackup_name == "all"
block:
- name: Get list of all backups on IPA server
ansible.builtin.shell:
find . -name "ipa-full-*" -o -name "ipa-data-*" | cut -d"/" -f 2
args:
chdir: "{{ ipabackup_dir }}/"
register: result_backup_find_backup_files
- name: Set ipabackup_names using backup list
ansible.builtin.set_fact:
ipabackup_names: "{{ result_backup_find_backup_files.stdout_lines }}"
- name: Set ipabackup_names from ipabackup_name
when: ipabackup_names is not defined and ipabackup_name is defined
block:
- name: Fail on ipabackup_name all
ansible.builtin.fail:
msg: "ipabackup_name can not be all in this case"
when: ipabackup_name is defined and ipabackup_name == "all"
- name: Set ipabackup_names from ipabackup_name string
ansible.builtin.set_fact:
ipabackup_names: ["{{ ipabackup_name }}"]
when: ipabackup_name | type_debug != "list"
- name: Set ipabackup_names from ipabackup_name list
ansible.builtin.set_fact:
ipabackup_names: "{{ ipabackup_name }}"
when: ipabackup_name | type_debug == "list"
- name: Set empty ipabackup_names if ipabackup_name is not defined
ansible.builtin.set_fact:
ipabackup_names: []
when: ipabackup_names is not defined and ipabackup_name is not defined
- name: Process "{{ ipabackup_names }}"
when: state is defined and
((state == "copied" and ipabackup_to_controller) or state == "absent")
block:
- name: Copy backup from IPA server
ansible.builtin.include_tasks: "{{ role_path }}/tasks/copy_backup_from_server.yml"
vars:
ipabackup_item: "{{ main_item | basename }}"
with_items:
- "{{ ipabackup_names }}"
loop_control:
loop_var: main_item
when: state is defined and state == "copied"
- name: Remove backup from IPA server
ansible.builtin.include_tasks: "{{ role_path }}/tasks/remove_backup_from_server.yml"
vars:
ipabackup_item: "{{ main_item | basename }}"
with_items:
- "{{ ipabackup_names }}"
loop_control:
loop_var: main_item
when: state is defined and state == "absent"
# Fail with more than one entry in ipabackup_names for copy to sever and
# restore.
- name: Fail to copy or restore more than one backup on the server
ansible.builtin.fail:
msg: "Only one backup can be copied to the server or restored"
when: state is defined and (state == "copied" or state == "restored") and
ipabackup_from_controller | bool and ipabackup_names | length != 1
# Use only first item in ipabackup_names for copy to server and for restore.
- name: Process "{{ ipabackup_names[0] }}"
when: ipabackup_from_controller or
(state|default("present") == "copied" and not ipabackup_to_controller)
vars:
ipabackup_name: "{{ ipabackup_names[0] }}"
block:
- name: Copy backup to server
ansible.builtin.include_tasks: "{{ role_path }}/tasks/copy_backup_to_server.yml"
- name: Restore IPA server after copy
ansible.builtin.include_tasks: "{{ role_path }}/tasks/restore.yml"
when: state|default("present") == "restored"
- name: Restore IPA server
ansible.builtin.include_tasks: "{{ role_path }}/tasks/restore.yml"
vars:
ipabackup_item: "{{ ipabackup_names[0] | basename }}"
when: not ipabackup_from_controller and
state|default("present") == "restored"
ansible-freeipa-master/roles/ipabackup/tasks/remove_backup_from_server.yml 0000664 0000000 0000000 00000000220 14600563364 0027564 0 ustar 00root root 0000000 0000000 ---
- name: Remove backup "{{ ipabackup_item }}"
ansible.builtin.file:
path: "{{ ipabackup_dir }}/{{ ipabackup_item }}"
state: absent
ansible-freeipa-master/roles/ipabackup/tasks/restore.yml 0000664 0000000 0000000 00000013266 14600563364 0024032 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipabackup
### VARIABLES
- name: Import variables specific to distribution
ansible.builtin.include_vars: "{{ item }}"
with_first_found:
- "{{ role_path }}/vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_version'] }}.yml"
- "{{ role_path }}/vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "{{ role_path }}/vars/{{ ansible_facts['distribution'] }}.yml"
# os_family is used as a fallback for distros which are not currently
# supported, but are based on a supported distro family. For example,
# Oracle, Rocky, Alma and Alibaba linux, which are all "RedHat" based.
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_version'] }}.yml"
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "vars/{{ ansible_facts['os_family'] }}.yml"
# If neither distro nor family is supported, try a default configuration.
- "{{ role_path }}/vars/default.yml"
### GET SERVICES FROM BACKUP
- name: Stat backup on server
ansible.builtin.stat:
path: "{{ ipabackup_dir }}/{{ ipabackup_item }}"
register: result_backup_stat
- name: Fail on missing backup directory
ansible.builtin.fail:
msg: "Unable to find backup {{ ipabackup_item }}"
when: result_backup_stat.stat.isdir is not defined
- name: Stat header file in backup "{{ ipabackup_item }}"
ansible.builtin.stat:
path: "{{ ipabackup_dir }}/{{ ipabackup_item }}/header"
register: result_backup_header_stat
- name: Fail on missing header file in backup
ansible.builtin.fail:
msg: "Unable to find backup {{ ipabackup_item }} header file"
when: result_backup_header_stat.stat.isreg is not defined
- name: Get services from backup
ansible.builtin.shell: >
grep "^services = " "{{ ipabackup_dir }}/{{ ipabackup_item }}/header" | cut -d"=" -f2 | tr -d '[:space:]'
register: result_services_grep
- name: Set ipabackup_services
ansible.builtin.set_fact:
ipabackup_services: "{{ result_services_grep.stdout.split(',') }}"
ipabackup_service_dns: DNS
ipabackup_service_adtrust: ADTRUST
ipabackup_service_ntp: NTP
### INSTALL PACKAGES
- name: Package installation
when: ipabackup_install_packages | bool
block:
- name: Ensure that IPA server packages are installed
ansible.builtin.package:
name: "{{ ipaserver_packages }}"
state: present
- name: Ensure that IPA server packages for dns are installed
ansible.builtin.package:
name: "{{ ipaserver_packages_dns }}"
state: present
when: ipabackup_service_dns in ipabackup_services
- name: Ensure that IPA server packages for adtrust are installed
ansible.builtin.package:
name: "{{ ipaserver_packages_adtrust }}"
state: present
when: ipabackup_service_adtrust in ipabackup_services
- name: Ensure that firewalld packages are installed
ansible.builtin.package:
name: "{{ ipaserver_packages_firewalld }}"
state: present
when: ipabackup_setup_firewalld | bool
### START FIREWALLD
- name: Firewall configuration
when: ipabackup_setup_firewalld | bool
block:
- name: Ensure that firewalld is running
ansible.builtin.systemd:
name: firewalld
enabled: yes
state: started
- name: Firewalld - Verify runtime zone "{{ ipabackup_firewalld_zone }}"
ansible.builtin.shell: >
firewall-cmd
--info-zone="{{ ipabackup_firewalld_zone }}"
>/dev/null
when: ipabackup_firewalld_zone is defined
- name: Firewalld - Verify permanent zone "{{ ipabackup_firewalld_zone }}"
ansible.builtin.shell: >
firewall-cmd
--permanent
--info-zone="{{ ipabackup_firewalld_zone }}"
>/dev/null
when: ipabackup_firewalld_zone is defined
### RESTORE
- name: Restore backup
no_log: True
ansible.builtin.shell: >
ipa-restore
{{ ipabackup_item }}
--unattended
{{ "--password=" + ipabackup_password if ipabackup_password is defined else "" }}
{{ "--data" if ipabackup_data | bool else "" }}
{{ "--online" if ipabackup_online | bool else "" }}
{{ "--instance=" + ipabackup_instance if ipabackup_instance is defined else "" }}
{{ "--backend=" + ipabackup_backend if ipabackup_backend is defined else "" }}
{{ "--no-logs" if ipabackup_no_logs | bool else "" }}
{{ "--log-file=" + ipabackup_log_file if ipabackup_log_file is defined else "" }}
register: result_iparestore
ignore_errors: yes
- name: Report error for restore operation
ansible.builtin.debug:
msg: "{{ result_iparestore.stderr }}"
when: result_iparestore is failed
failed_when: yes
### CONFIGURE FIREWALLD
- name: Configure firewalld
ansible.builtin.command: >
firewall-cmd
--permanent
{{ "--zone=" + ipabackup_firewalld_zone if ipabackup_firewalld_zone is defined else "" }}
--add-service=freeipa-ldap
--add-service=freeipa-ldaps
{{ "--add-service=freeipa-trust" if ipabackup_service_adtrust in ipabackup_services else "" }}
{{ "--add-service=dns" if ipabackup_service_dns in ipabackup_services else "" }}
{{ "--add-service=ntp" if ipabackup_service_ntp in ipabackup_services else "" }}
when: ipabackup_setup_firewalld | bool
- name: Configure firewalld runtime
ansible.builtin.command: >
firewall-cmd
{{ "--zone=" + ipabackup_firewalld_zone if ipabackup_firewalld_zone is defined else "" }}
--add-service=freeipa-ldap
--add-service=freeipa-ldaps
{{ "--add-service=freeipa-trust" if ipabackup_service_adtrust in ipabackup_services else "" }}
{{ "--add-service=dns" if ipabackup_service_dns in ipabackup_services else "" }}
{{ "--add-service=ntp" if ipabackup_service_ntp in ipabackup_services else "" }}
when: ipabackup_setup_firewalld | bool
ansible-freeipa-master/roles/ipabackup/vars/ 0000775 0000000 0000000 00000000000 14600563364 0021442 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipabackup/vars/Fedora.yml 0000664 0000000 0000000 00000000366 14600563364 0023372 0 ustar 00root root 0000000 0000000 # defaults file for ipabackup
# vars/Fedora.yml
---
ipaserver_packages: [ "freeipa-server" ]
ipaserver_packages_dns: [ "freeipa-server-dns" ]
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipabackup/vars/RedHat-7.yml 0000664 0000000 0000000 00000000401 14600563364 0023473 0 ustar 00root root 0000000 0000000 # defaults file for ipabackup
# vars/RedHat-7.yml
---
ipaserver_packages: [ "ipa-server", "libselinux-python" ]
ipaserver_packages_dns: [ "ipa-server-dns" ]
ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipabackup/vars/RedHat-8.yml 0000664 0000000 0000000 00000000354 14600563364 0023503 0 ustar 00root root 0000000 0000000 # defaults file for ipabackup
# vars/RedHat-8.yml
---
ipaserver_packages: [ "@idm:DL1/server" ]
ipaserver_packages_dns: [ "@idm:DL1/dns" ]
ipaserver_packages_adtrust: [ "@idm:DL1/adtrust" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipabackup/vars/Ubuntu-18.04.yml 0000664 0000000 0000000 00000000674 14600563364 0024126 0 ustar 00root root 0000000 0000000 # vars/Ubuntu.yml
---
ipaserver_packages: [ "freeipa-server" ]
ipaserver_packages_dns: [ "freeipa-server-dns" ]
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
# Ubuntu Bionic Beaver must use python2 as Python interpreter due
# to the way python-ipalib package is defined.
# Package python2.7 must be installed before executing this role.
ansible_python_interpreter: '/usr/bin/python2.7'
ansible-freeipa-master/roles/ipabackup/vars/Ubuntu.yml 0000664 0000000 0000000 00000000366 14600563364 0023454 0 ustar 00root root 0000000 0000000 # defaults file for ipabackup
# vars/Ubuntu.yml
---
ipaserver_packages: [ "freeipa-server" ]
ipaserver_packages_dns: [ "freeipa-server-dns" ]
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipabackup/vars/default.yml 0000664 0000000 0000000 00000000357 14600563364 0023616 0 ustar 00root root 0000000 0000000 # defaults file for ipabackup
# vars/default.yml
---
ipaserver_packages: [ "ipa-server" ]
ipaserver_packages_dns: [ "ipa-server-dns" ]
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipaclient/ 0000775 0000000 0000000 00000000000 14600563364 0020500 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaclient/README.md 0000664 0000000 0000000 00000031431 14600563364 0021761 0 ustar 00root root 0000000 0000000 ipaclient role
==============
This [Ansible](https://www.ansible.com/) role allows to join hosts as clients to an IPA domain. This can be done in different ways using auto-discovery of the servers, domain and other settings or by specifying them.
**Note**: The ansible playbooks and role require a configured ansible environment where the ansible nodes are reachable and are properly set up to have an IP address and a working package manager.
Features
--------
* Client deployment
* One-time-password (OTP) support
* Repair mode
* DNS resolver configuration support
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.5 and up are supported by the client role. There is also limited support for version 4.4.
Supported Distributions
-----------------------
* RHEL/CentOS 7.4+
* CentOS Stream 8+
* Fedora 26+
* Ubuntu
* Debian
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
* Supported distribution (needed for package installation only, see above)
Usage
=====
Example inventory file with fixed principal using auto-discovery with DNS records:
```ini
[ipaclients]
ipaclient1.example.com
ipaclient2.example.com
[ipaclients:vars]
ipaadmin_principal=admin
```
Example playbook to setup the IPA client(s) using principal from inventory file and password from an [Ansible Vault](http://docs.ansible.com/ansible/latest/playbooks_vault.html) file:
```yaml
- name: Playbook to configure IPA clients with username/password
hosts: ipaclients
become: true
vars_files:
- playbook_sensitive_data.yml
roles:
- role: ipaclient
state: present
```
Example playbook to unconfigure the IPA client(s) using principal and password from inventory file:
```yaml
- name: Playbook to unconfigure IPA clients
hosts: ipaclients
become: true
roles:
- role: ipaclient
state: absent
```
Example inventory file with fixed servers, principal, password and domain:
```ini
[ipaclients]
ipaclient1.example.com
ipaclient2.example.com
[ipaservers]
ipaserver.example.com
[ipaclients:vars]
ipaclient_domain=example.com
ipaadmin_principal=admin
ipaadmin_password=MySecretPassword123
```
Example playbook to setup the IPA client(s) using principal and password from inventory file:
```yaml
- name: Playbook to configure IPA clients with username/password
hosts: ipaclients
become: true
roles:
- role: ipaclient
state: present
```
Example inventory file with configuration of dns resolvers:
```ini
[ipaclients]
ipaclient1.example.com
ipaclient2.example.com
[ipaservers]
ipaserver.example.com
[ipaclients:vars]
ipaadmin_principal=admin
ipaadmin_password=MySecretPassword123
ipaclient_domain=example.com
ipaclient_configure_dns_resolver=yes
ipaclient_dns_servers=192.168.100.1
```
Example inventory file with cleanup of dns resolvers:
```ini
[ipaclients]
ipaclient1.example.com
ipaclient2.example.com
[ipaservers]
ipaserver.example.com
[ipaclients:vars]
ipaadmin_principal=admin
ipaadmin_password=MySecretPassword123
ipaclient_domain=example.com
ipaclient_cleanup_dns_resolver=yes
```
Playbooks
=========
The playbooks needed to deploy or undeploy a client are part of the repository in the playbooks folder. There are also playbooks to deploy and undeploy clusters.
```
install-client.yml
uninstall-client.yml
```
Please remember to link or copy the playbooks to the base directory of ansible-freeipa if you want to use the roles within the source archive.
How to setup a client
---------------------
```bash
ansible-playbook -v -i inventory/hosts install-client.yml
```
This will deploy the clients defined in the inventory file.
Variables
=========
Base Variables
--------------
Variable | Description | Required
-------- | ----------- | --------
`ipaclients` | This group is a list of the names of the IPA clients in FQDN form. All these clients will be installed or configured using the playbook. | yes
`ipaclient_domain` | This string value sets the DNS domain that will be used for client installation. Usually the DNS domain is a lower-cased name of the Kerberos realm. If the role is for example used in a cluster inventory and `ipaserver_domain` is set, then it will be used. | no
`ipaclient_realm` | This string value sets the Kerberos realm that will be used for client installation. Usually the Kerberos realm is an upper-cased name of the DNS domain. If the role is for example used in a cluster inventory and `ipaserver_realm` is set, then it will be used. If `ipaclient_realm` is not set, then it will be generated from `ipaclient_domain` if this is set. | no
`ipaclient_mkhomedir` | This bool value defines if PAM will be configured to create a users home directory if it does not exist. `ipaclient_mkhomedir` defaults to `no`. | no
`ipaclient_force_join` | This bool value defines if an already enrolled host can join again. `ipaclient_force_join` defaults to `no`. | no
`ipaclient_kinit_attempts` | The int value defines the number of tries to repeat the request for a failed host Kerberos ticket. `ipaclient_kinit_attempts` defaults to 5.| no
`ipaclient_ntp_servers` | The list defines the NTP servers to be used. | no
`ipaclient_ntp_pool` | The string value defines the ntp server pool to be used. | no
`ipaclient_no_ntp` | The bool value defines if NTP will not be configured and enabled. `ipaclient_no_ntp` defaults to `no`. | no
`ipaclient_ssh_trust_dns` | The bool value defines if OpenSSH client will be configured to trust DNS SSHFP records. `ipaclient_ssh_trust_dns` defaults to `no`. | no
`ipaclient_no_ssh` | The bool value defines if OpenSSH client will be configured. `ipaclient_no_ssh` defaults to `no`. | no
`ipaclient_no_sshd` | The bool value defines if OpenSSH server will be configured. `ipaclient_no_sshd` defaults to `no`. | no
`ipaclient_no_sudo` | The bool value defines if SSSD will be configured as a data source for sudo. `ipaclient_no_sudo` defaults to `no`. | no
`ipaclient_subid` | The bool value defines if SSSD will be configured as a data source for subid. `ipaclient_subid` defaults to `no`. | no
`ipaclient_no_dns_sshfp` | The bool value defines if DNS SSHFP records will not be created automatically. `ipaclient_no_dns_sshfp` defaults to `no`. | no
`ipaclient_force` | The bool value defines if settings will be forced even in the error case. `ipaclient_force` defaults to `no`. | no
`ipaclient_force_ntpd` | The bool value defines if ntpd usage will be forced. This is not supported anymore and leads to a warning. `ipaclient_force_ntpd` defaults to `no`. | no
`ipaclient_nisdomain` | This string value defines the NIS domain name. | no
`ipaclient_no_nisdomain` | The bool value defines if the NIS domain name will not be configured. `ipaclient_no_nisdomain` defaults to `no`. | no
`ipaclient_configure_firefox` | The bool value defines if Firefox will be configured to use IPA domain credentials. `ipaclient_configure_firefox` defaults to `no`. | no
`ipaclient_firefox_dir` | The string value defines the Firefox installation directory. For example: '/usr/lib/firefox'. | no
`ipaclient_all_ip_addresses` | The bool value defines if DNS A/AAAA records for each IP address on the client will be created. `ipaclient_all_ip_addresses` defaults to `no`. | no
`ipasssd_fixed_primary` | The bool value defines if SSSD will be configured to use a fixed server as the primary IPA server. `ipasssd_fixed_primary` defaults to `no`. | no
`ipasssd_permit` | The bool value defines if SSSD will be configured to permit all access. Otherwise the machine will be controlled by the Host-based Access Controls (HBAC) on the IPA server. `ipasssd_permit` defaults to `no`. | no
`ipasssd_enable_dns_updates` | The bool value tells SSSD to automatically update DNS with the IP address of this client. `ipasssd_enable_dns_updates` defaults to `no`. | no
`ipasssd_no_krb5_offline_passwords` | The bool value defines if SSSD will be configured not to store user password when the server is offline . `ipasssd_no_krb5_offline_passwords` defaults to `no`. | no
`ipasssd_preserve_sssd` | The bool value defines if the old SSSD configuration will be preserved if it is not possible to merge it with a new one. `ipasssd_preserve_sssd` defaults to `no`. | no
`ipaclient_request_cert` | The bool value defines if the certificate for the machine wil be requested. The certificate will be stored in /etc/ipa/nssdb under the nickname "Local IPA host". . `ipaclient_request_cert` defaults to `no`. The option is deprecated and will be removed in a future release. | no
`ipaclient_keytab` | The string value contains the path on the node of a backup host keytab from a previous enrollment. | no
`ipaclient_automount_location` | Automount location | no
Server Variables
----------------
Variable | Description | Required
-------- | ----------- | --------
`ipaservers` | This group is a list of the IPA server full qualified host names. In a topology with a chain of servers and replicas, it is important to use the right server or replica as the server for the client. If there is a need to overwrite the setting for a client in the `ipaclients` group, please use the list `ipaclient_servers` explained below. If no `ipaservers` group is defined than the installation preparation step will try to use DNS autodiscovery to identify the the IPA server using DNS txt records. | mostly
`ipaadmin_keytab` | The string variable enables the use of an admin keytab as an alternative authentication method. The variable needs to contain the local path to the keytab file. If `ipaadmin_keytab` is used, then `ipaadmin_password` does not need to be set. If `ipaadmin_keytab` is used with `ipaclient_use_otp: yes` then the keytab needs to be available on the controller, else on the client node. The use of full path names is recommended. | no
`ipaadmin_principal` | The string variable only needs to be set if the name of the Kerberos admin principal is not "admin". If `ipaadmin_principal` is not set it will be set internally to "admin". | no
`ipaadmin_password` | The string variable contains the Kerberos password of the Kerberos admin principal. If `ipaadmin_keytab` is used, then `ipaadmin_password` does not need to be set. | mostly
Topology Variables
------------------
These variables can be used to define or change how clients are arranged within a cluster for example.
Variable | Description | Required
-------- | ----------- | --------
`ipaclient_no_dns_lookup` | The bool value defines if the `ipaservers` group will be used as servers for the clients automatically. If enabled this deactivates DNS lookup in Kerberos in client installations. `ipaclient_no_dns_lookup` defaults to `no`. | no
`ipaclient_servers` | The optional list can be used to manually override list of servers on a per client basis. The list of servers is normally taken from from `ipaservers` group. | no
Special Variables
-----------------
Variable | Description | Required
-------- | ----------- | --------
`ipaclient_use_otp` | The bool value defines if a one-time password will be generated to join a new or existing host. `ipaclient_use_otp` defaults to `no`. The enforcement on an existing host is not done if there is a working krb5.keytab on the host. If the generation of an otp is enforced for an existing host entry, then the host gets disabled and the containing keytab gets removed. | no
`ipaclient_otp` | The string value sets an already generated one-time password for the host. The role will use it and not try to generate a new one. Do not enable `ipaclient_use_otp` additionally. | no
`ipaclient_allow_repair` | The bool value defines if an already joined or partly set-up client can be repaired. `ipaclient_allow_repair` defaults to `no`. Contrary to `ipaclient_force_join=yes` the host entry will not be changed on the server. | no
`ipaclient_install_packages` | The bool value defines if the needed packages are installed on the node. `ipaclient_install_packages` defaults to `yes`. | no
`ipaclient_on_master` | The bool value is only used in the server and replica installation process to install the client part. It should not be set otherwise. `ipaclient_on_master` defaults to `no`. | no
`ipaclient_configure_dns_resolver` | The bool value defines if the DNS resolver is configured. This is useful if the IPA server has internal DNS support. `ipaclient_dns_server` need to be set also. The installation of packages is happening before the DNS resolver is configured, therefore package installation needs to be possible without the configuration of the DNS resolver. The DNS nameservers are configured for `NetworkManager`, `systemd-resolved` (if installed and enabled) and `/etc/resolv.conf` if neither NetworkManager nor systemd-resolved is used. | no
`ipaclient_dns_servers` | The list of DNS server IP addresses. This is only useful with `ipaclient_configure_dns_resolver`. | no
`ipaclient_cleanup_dns_resolver` | The bool value defines if DNS resolvers that have been configured before with `ipaclient_configure_dns_resolver` will be cleaned up again. | no
Authors
=======
Florence Blanc-Renaud
Thomas Woerner
ansible-freeipa-master/roles/ipaclient/defaults/ 0000775 0000000 0000000 00000000000 14600563364 0022307 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaclient/defaults/main.yml 0000664 0000000 0000000 00000001437 14600563364 0023763 0 ustar 00root root 0000000 0000000 ---
# defaults file for ipaclient
ipaclient_force_join: no
ipaclient_mkhomedir: no
ipaclient_kinit_attempts: 5
ipaclient_use_otp: no
ipaclient_allow_repair: no
ipaclient_on_master: no
ipaclient_no_ntp: no
ipaclient_no_dns_lookup: no
ipaclient_ssh_trust_dns: no
ipaclient_no_ssh: no
ipaclient_no_sshd: no
ipaclient_no_sudo: no
ipaclient_subid: no
ipaclient_no_dns_sshfp: no
ipaclient_force: no
ipaclient_force_ntpd: no
ipaclient_no_nisdomain: no
ipaclient_configure_firefox: no
ipaclient_all_ip_addresses: no
ipasssd_fixed_primary: no
ipasssd_permit: no
ipasssd_enable_dns_updates: no
ipasssd_no_krb5_offline_passwords: no
ipasssd_preserve_sssd: no
ipaclient_request_cert: no
### packages ###
ipaclient_install_packages: yes
ipaclient_configure_dns_resolver: no
ipaclient_cleanup_dns_resolver: no
ansible-freeipa-master/roles/ipaclient/library/ 0000775 0000000 0000000 00000000000 14600563364 0022144 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaclient/library/ipaclient_api.py 0000664 0000000 0000000 00000020560 14600563364 0025322 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.0',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: ipaclient_api
short_description:
Create temporary NSS database, call IPA API for remaining enrollment parts
description:
Create temporary NSS database, call IPA API for remaining enrollment parts
options:
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: yes
debug:
description: Turn on extra debugging
type: bool
required: no
default: no
krb_name:
description: The krb5 config file name
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
- name: IPA API calls for remaining enrollment parts
ipaclient_api:
servers: ["server1.example.com","server2.example.com"]
domain: example.com
hostname: client1.example.com
krb_name: /tmp/tmpkrb5.conf
register: result_ipaclient_api
'''
RETURN = '''
ca_enabled:
description: Wheter the Certificate Authority is enabled or not.
returned: always
type: bool
subject_base:
description: The subject base, needed for certmonger
returned: always
type: str
sample: O=EXAMPLE.COM
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports,
paths, x509, NUM_VERSION, serialization, certdb, api,
delete_persistent_client_session_data, write_tmp_file,
ipa_generate_password, CalledProcessError, errors, disable_ra, DN,
CLIENT_INSTALL_ERROR, logger, getargspec
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list', elements='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=True, type='str'),
debug=dict(required=False, type='bool', default="false"),
krb_name=dict(required=True, type='str'),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
realm = module.params.get('realm')
hostname = module.params.get('hostname')
debug = module.params.get('debug')
krb_name = module.params.get('krb_name')
host_principal = 'host/%s@%s' % (hostname, realm)
os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
os.environ['KRB5_CONFIG'] = krb_name
ca_certs = x509.load_certificate_list_from_file(paths.IPA_CA_CRT)
if 40500 <= NUM_VERSION < 40590:
ca_certs = [cert.public_bytes(serialization.Encoding.DER)
for cert in ca_certs]
elif NUM_VERSION < 40500:
ca_certs = [cert.der_data for cert in ca_certs]
with certdb.NSSDatabase() as tmp_db:
api.bootstrap(context='cli_installer',
confdir=paths.ETC_IPA,
debug=debug,
delegate=False,
nss_dir=tmp_db.secdir)
if 'config_loaded' not in api.env:
module.fail_json(msg="Failed to initialize IPA API.")
# Clear out any current session keyring information
try:
delete_persistent_client_session_data(host_principal)
except ValueError:
pass
# Add CA certs to a temporary NSS database
try:
# pylint: disable=deprecated-method
argspec = getargspec(tmp_db.create_db)
# pylint: enable=deprecated-method
if "password_filename" not in argspec.args:
tmp_db.create_db()
else:
pwd_file = write_tmp_file(ipa_generate_password())
tmp_db.create_db(pwd_file.name)
for i, cert in enumerate(ca_certs):
if hasattr(certdb, "EXTERNAL_CA_TRUST_FLAGS"):
tmp_db.add_cert(cert,
'CA certificate %d' % (i + 1),
certdb.EXTERNAL_CA_TRUST_FLAGS)
else:
tmp_db.add_cert(cert, 'CA certificate %d' % (i + 1),
'C,,')
except CalledProcessError:
module.fail_json(msg="Failed to add CA to temporary NSS database.")
api.finalize()
# Now, let's try to connect to the server's RPC interface
connected = False
try:
api.Backend.rpcclient.connect()
connected = True
module.debug("Try RPC connection")
api.Backend.rpcclient.forward('ping')
except errors.KerberosError as e:
if connected:
api.Backend.rpcclient.disconnect()
module.log(
"Cannot connect to the server due to Kerberos error: %s. "
"Trying with delegate=True" % e)
try:
api.Backend.rpcclient.connect(delegate=True)
module.debug("Try RPC connection")
api.Backend.rpcclient.forward('ping')
module.log("Connection with delegate=True successful")
# The remote server is not capable of Kerberos S4U2Proxy
# delegation. This features is implemented in IPA server
# version 2.2 and higher
module.warn(
"Target IPA server has a lower version than the enrolled "
"client")
module.warn(
"Some capabilities including the ipa command capability "
"may not be available")
except errors.PublicError as e2: # pylint: disable=invalid-name
module.fail_json(
msg="Cannot connect to the IPA server RPC interface: "
"%s" % e2)
except errors.PublicError as e:
module.fail_json(
msg="Cannot connect to the server due to generic error: "
"%s" % e)
# Use the RPC directly so older servers are supported
try:
result = api.Backend.rpcclient.forward(
'ca_is_enabled',
version=u'2.107',
)
ca_enabled = result['result']
except (errors.CommandError, errors.NetworkError):
result = api.Backend.rpcclient.forward(
'env',
server=True,
version=u'2.0',
)
ca_enabled = result['result']['enable_ra']
if not ca_enabled:
disable_ra()
# Get subject base from ipa server
try:
config = api.Command['config_show']()['result']
subject_base = str(DN(config['ipacertificatesubjectbase'][0]))
except errors.PublicError:
try:
config = api.Backend.rpcclient.forward(
'config_show',
raw=True, # so that servroles are not queried
version=u'2.0'
)['result']
except Exception as e:
logger.debug("config_show failed %s", e, exc_info=True)
module.fail_json(
"Failed to retrieve CA certificate subject base: "
"{0}".format(e),
rval=CLIENT_INSTALL_ERROR)
else:
subject_base = str(DN(config['ipacertificatesubjectbase'][0]))
module.exit_json(changed=True,
ca_enabled=ca_enabled,
subject_base=subject_base)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_configure_dns_resolver.py 0000664 0000000 0000000 00000024675 14600563364 0031332 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipaplatform/redhat/tasks.py code from Christian Heimes
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = """
---
module: ipaclient_configure_dns_resolver
short_description: Configure DNS resolver for IPA client
description:
Configure DNS resolver for IPA client, register files for installer
options:
nameservers:
description: The nameservers, required with state:present.
type: list
elements: str
required: false
searchdomains:
description: The searchdomains, required with state:present.
type: list
elements: str
required: false
state:
description: The state to ensure.
type: str
choices: ["present", "absent"]
default: present
required: false
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
# Ensure DNS nameservers and domain are configured
- ipaclient_configure_dns_resolver:
nameservers: groups.ipaservers
searchdomains: "{{ ipaserver_domain | default(ipaclient_domain) }}"
# Ensure DNS nameservers and domain are not configured
- ipaclient_configure_dns_resolver:
state: absent
"""
RETURN = """
"""
import os
import os.path
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
check_imports, services, tasks, paths, sysrestore, CheckedIPAddress
)
try:
from ipalib.installdnsforwarders import detect_resolve1_resolv_conf
except ImportError:
def detect_resolve1_resolv_conf():
"""
Detect if /etc/resolv.conf is managed by systemd-resolved.
See man(5) NetworkManager.conf
"""
systemd_resolv_conf_files = {
"/run/systemd/resolve/stub-resolv.conf",
"/run/systemd/resolve/resolv.conf",
"/lib/systemd/resolv.conf",
"/usr/lib/systemd/resolv.conf",
}
try:
dest = os.readlink(paths.RESOLV_CONF)
except OSError:
# not a link
return False
# convert path relative to /etc/resolv.conf to abs path
dest = os.path.normpath(
os.path.join(os.path.dirname(paths.RESOLV_CONF), dest)
)
return dest in systemd_resolv_conf_files
if hasattr(paths, "SYSTEMD_RESOLVED_IPA_CONF"):
SYSTEMD_RESOLVED_IPA_CONF = paths.SYSTEMD_RESOLVED_IPA_CONF
else:
SYSTEMD_RESOLVED_IPA_CONF = "/etc/systemd/resolved.conf.d/zzz-ipa.conf"
if hasattr(paths, "NETWORK_MANAGER_IPA_CONF"):
NETWORK_MANAGER_IPA_CONF = paths.NETWORK_MANAGER_IPA_CONF
else:
NETWORK_MANAGER_IPA_CONF = "/etc/NetworkManager/conf.d/zzz-ipa.conf"
NM_IPA_CONF = """
# auto-generated by IPA client installer
[main]
dns={dnsprocessing}
[global-dns]
searches={searches}
[global-dns-domain-*]
servers={servers}
"""
RESOLVE1_IPA_CONF = """
# auto-generated by IPA client installer
[Resolve]
# use DNS servers
DNS={servers}
# make default DNS server, add search suffixes
Domains=~. {searchdomains}
"""
def configure_dns_resolver(nameservers, searchdomains, fstore=None):
"""
Configure global DNS resolver (e.g. /etc/resolv.conf).
:param nameservers: list of IP addresses
:param searchdomains: list of search domaons
:param fstore: optional file store for resolv.conf backup
"""
if not nameservers or not isinstance(nameservers, list):
raise AssertionError("nameservers must be of type list")
if not searchdomains or not isinstance(searchdomains, list):
raise AssertionError("searchdomains must be of type list")
if fstore is not None and not fstore.has_file(paths.RESOLV_CONF):
fstore.backup_file(paths.RESOLV_CONF)
resolve1_enabled = detect_resolve1_resolv_conf()
if "NetworkManager" not in services.knownservices:
# NetworkManager is not in wellknownservices for old IPA releases
# Therefore create own service for it.
nm_service = services.service("NetworkManager.service")
else:
nm_service = services.knownservices['NetworkManager']
# At first configure systemd-resolved
if resolve1_enabled:
if not os.path.exists(SYSTEMD_RESOLVED_IPA_CONF):
confd = os.path.dirname(SYSTEMD_RESOLVED_IPA_CONF)
if not os.path.isdir(confd):
os.mkdir(confd)
# owned by root, readable by systemd-resolve user
os.chmod(confd, 0o755)
tasks.restore_context(confd, force=True)
# Additionally to IPA server code also set servers
cfg = RESOLVE1_IPA_CONF.format(
servers=' '.join(nameservers),
searchdomains=" ".join(searchdomains)
)
with open(SYSTEMD_RESOLVED_IPA_CONF, "w") as outf:
os.fchmod(outf.fileno(), 0o644)
outf.write(cfg)
tasks.restore_context(
SYSTEMD_RESOLVED_IPA_CONF, force=True
)
if "systemd-resolved" in services.knownservices:
sdrd_service = services.knownservices["systemd-resolved"]
else:
sdrd_service = services.service("systemd-resolved.service")
if sdrd_service.is_enabled():
sdrd_service.reload_or_restart()
# Then configure NetworkManager or resolve.conf
if nm_service.is_enabled():
if not os.path.exists(NETWORK_MANAGER_IPA_CONF):
# write DNS override and reload network manager to have it create
# a new resolv.conf. The file is prefixed with ``zzz`` to
# make it the last file. Global dns options do not stack and last
# man standing wins.
if resolve1_enabled:
# push DNS configuration to systemd-resolved
dnsprocessing = "systemd-resolved"
else:
# update /etc/resolv.conf
dnsprocessing = "default"
cfg = NM_IPA_CONF.format(
dnsprocessing=dnsprocessing,
servers=','.join(nameservers),
searches=','.join(searchdomains)
)
with open(NETWORK_MANAGER_IPA_CONF, 'w') as outf:
os.fchmod(outf.fileno(), 0o644)
outf.write(cfg)
# reload NetworkManager
nm_service.reload_or_restart()
# Configure resolv.conf if NetworkManager and systemd-resoled are not
# enabled
elif not resolve1_enabled:
# no NM running, no systemd-resolved detected
# fall back to /etc/resolv.conf
cfg = [
"# auto-generated by IPA installer",
"search %s" % ' '.join(searchdomains),
]
for nameserver in nameservers:
cfg.append("nameserver %s" % nameserver)
with open(paths.RESOLV_CONF, 'w') as outf:
outf.write('\n'.join(cfg))
def unconfigure_dns_resolver(fstore=None):
"""
Unconfigure global DNS resolver (e.g. /etc/resolv.conf).
:param fstore: optional file store for resolv.conf restore
"""
if fstore is not None and fstore.has_file(paths.RESOLV_CONF):
fstore.restore_file(paths.RESOLV_CONF)
if os.path.isfile(NETWORK_MANAGER_IPA_CONF):
os.unlink(NETWORK_MANAGER_IPA_CONF)
if "NetworkManager" not in services.knownservices:
# NetworkManager is not in wellknownservices for old IPA releases
# Therefore create own service for it.
nm_service = services.service("NetworkManager.service")
else:
nm_service = services.knownservices['NetworkManager']
if nm_service.is_enabled():
nm_service.reload_or_restart()
if os.path.isfile(SYSTEMD_RESOLVED_IPA_CONF):
os.unlink(SYSTEMD_RESOLVED_IPA_CONF)
if "systemd-resolved" in services.knownservices:
sdrd_service = services.knownservices["systemd-resolved"]
else:
sdrd_service = services.service("systemd-resolved.service")
if sdrd_service.is_enabled():
sdrd_service.reload_or_restart()
def main():
module = AnsibleModule(
argument_spec=dict(
nameservers=dict(type="list", elements="str", required=False),
searchdomains=dict(type="list", elements="str", required=False),
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=False,
)
check_imports(module)
nameservers = module.params.get('nameservers')
searchdomains = module.params.get('searchdomains')
state = module.params.get("state")
if state == "present":
required = ["nameservers", "searchdomains"]
for param in required:
value = module.params.get(param)
if value is None or len(value) < 1:
module.fail_json(
msg="Argument '%s' is required for state:present" % param)
else:
invalid = ["nameservers", "searchdomains"]
for param in invalid:
if module.params.get(param) is not None:
module.fail_json(
msg="Argument '%s' can not be used with state:present" %
param)
# Check nameservers to contain valid IP addresses
if nameservers is not None:
for value in nameservers:
try:
CheckedIPAddress(value)
except Exception as e:
module.fail_json(
msg="Invalid IP address %s: %s" % (value, str(e)))
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
if state == "present":
configure_dns_resolver(nameservers, searchdomains, fstore)
else:
unconfigure_dns_resolver(fstore)
module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_fix_ca.py 0000664 0000000 0000000 00000010336 14600563364 0026002 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.0',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: ipaclient_fix_ca
short_description: Fix IPA ca certificate
description: Fix IPA ca certificate
options:
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
basedn:
description: The basedn of the IPA server (of the form dc=example,dc=com)
type: str
required: yes
allow_repair:
description: |
Allow repair of already joined hosts. Contrary to ipaclient_force_join
the host entry will not be changed on the server
type: bool
required: yes
krb_name:
description: The krb5 config file name
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
- name: Fix IPA ca certificate
ipaclient_fix_ca:
servers: ["server1.example.com","server2.example.com"]
realm: EXAMPLE.COM
basedn: dc=example,dc=com
allow_repair: yes
krb_name: /tmp/tmpkrb5.conf
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports,
SECURE_PATH, paths, sysrestore, options, NUM_VERSION, get_ca_cert,
get_ca_certs, errors
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list', elements='str'),
realm=dict(required=True, type='str'),
basedn=dict(required=True, type='str'),
allow_repair=dict(required=True, type='bool'),
krb_name=dict(required=True, type='str'),
),
)
module._ansible_debug = True
check_imports(module)
setup_logging()
servers = module.params.get('servers')
realm = module.params.get('realm')
basedn = module.params.get('basedn')
allow_repair = module.params.get('allow_repair')
krb_name = module.params.get('krb_name')
os.environ['KRB5_CONFIG'] = krb_name
env = {'PATH': SECURE_PATH}
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
options.ca_cert_file = None
options.principal = None
options.force = False
options.password = None
changed = False
if not os.path.exists(paths.IPA_CA_CRT):
if not allow_repair:
module.fail_json(
msg="%s missing, enable allow_repair to fix it." %
paths.IPA_CA_CRT)
# Repair missing ca.crt file
try:
os.environ['KRB5_CONFIG'] = env['KRB5_CONFIG'] = "/etc/krb5.conf"
env['KRB5CCNAME'] = os.environ['KRB5CCNAME']
if NUM_VERSION < 40100:
get_ca_cert(fstore, options, servers[0], basedn)
else:
get_ca_certs(fstore, options, servers[0], basedn, realm)
changed = True
os.environ.pop('KRB5_CONFIG', None)
except errors.FileError as e:
module.fail_json(msg='%s' % e)
except Exception as e:
module.fail_json(msg="Cannot obtain CA certificate\n%s" % e)
module.exit_json(changed=changed)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_fstore.py 0000664 0000000 0000000 00000004122 14600563364 0026047 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_fstore
short_description: Backup files using IPA client sysrestore
description: Backup files using IPA client sysrestore
options:
backup:
description: File to backup
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
- name: Backup /etc/krb5.conf
ipaclient_fstore:
backup: "/etc/krb5.conf"
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports, paths, sysrestore
)
def main():
module = AnsibleModule(
argument_spec=dict(
backup=dict(required=True, type='str'),
),
)
module._ansible_debug = True
check_imports(module)
setup_logging()
backup = module.params.get('backup')
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
if not fstore.has_file(backup):
fstore.backup_file(backup)
module.exit_json(changed=True)
module.exit_json(changed=False)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_get_otp.py 0000664 0000000 0000000 00000020177 14600563364 0026216 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaclient_get_otp
short_description: Get OTP for host enrollment
description: Get OTP for host enrollment
options:
ipaadmin_principal:
description: The admin principal.
default: admin
type: str
ipaadmin_password:
description: |
The admin password. Either ipaadmin_password or ipaadmin_keytab needs
to be given.
required: false
type: str
ipaadmin_keytab:
description: |
The admin keytab. Either ipaadmin_password or ipaadmin_keytab needs
to be given.
type: str
required: false
hostname:
description: The FQDN hostname.
type: str
required: true
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
"""
RETURN = """
host:
description: Host dict with random password
returned: always
type: dict
contains:
randompassword:
description: The generated random password
type: str
"""
import os
import tempfile
import shutil
from contextlib import contextmanager
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils import six
try:
from ipalib import api
from ipalib import errors as ipalib_errors # noqa
from ipalib.config import Env
from ipaplatform.paths import paths
from ipapython.ipautil import run
from ipalib.constants import DEFAULT_CONFIG
try:
from ipalib.install.kinit import kinit_password, kinit_keytab
except ImportError:
from ipapython.ipautil import kinit_password, kinit_keytab
except ImportError as _err:
MODULE_IMPORT_ERROR = str(_err)
else:
MODULE_IMPORT_ERROR = None
if six.PY3:
unicode = str
def temp_kinit(principal, password, keytab):
"""Kinit with password or keytab using a temporary ccache."""
ccache_dir = tempfile.mkdtemp(prefix='krbcc')
ccache_name = os.path.join(ccache_dir, 'ccache')
try:
if password:
kinit_password(principal, password, ccache_name)
else:
kinit_keytab(principal, keytab, ccache_name)
except RuntimeError as e:
raise RuntimeError("Kerberos authentication failed: %s" % str(e))
os.environ["KRB5CCNAME"] = ccache_name
return ccache_dir, ccache_name
def temp_kdestroy(ccache_dir, ccache_name):
"""Destroy temporary ticket and remove temporary ccache."""
if ccache_name is not None:
run([paths.KDESTROY, '-c', ccache_name], raiseonerr=False)
os.environ.pop('KRB5CCNAME', None)
if ccache_dir is not None:
shutil.rmtree(ccache_dir, ignore_errors=True)
@contextmanager
def ipa_connect(module, principal=None, password=None, keytab=None):
"""
Create a context with a connection to IPA API.
Parameters
----------
module: AnsibleModule
The AnsibleModule to use
principal: string
The optional principal name
password: string
The optional password. Either password or keytab needs to be given.
keytab: string
The optional keytab. Either password or keytab needs to be given.
"""
if not password and not keytab:
module.fail_json(msg="One of password and keytab is required.")
if not principal:
principal = "admin"
ccache_dir = None
ccache_name = None
try:
ccache_dir, ccache_name = temp_kinit(principal, password, keytab)
# api_connect start
env = Env()
env._bootstrap()
env._finalize_core(**dict(DEFAULT_CONFIG))
api.bootstrap(context="server", debug=env.debug, log=None)
api.finalize()
if api.env.in_server:
backend = api.Backend.ldap2
else:
backend = api.Backend.rpcclient
if not backend.isconnected():
backend.connect(ccache=ccache_name)
# api_connect end
except Exception as e:
module.fail_json(msg=str(e))
else:
try:
yield ccache_name
except Exception as e:
module.fail_json(msg=str(e))
finally:
temp_kdestroy(ccache_dir, ccache_name)
def ipa_command(command, name, args):
"""
Execute an IPA API command with a required `name` argument.
Parameters
----------
command: string
The IPA API command to execute.
name: string
The name parameter to pass to the command.
args: dict
The parameters to pass to the command.
"""
return api.Command[command](name, **args)
def _afm_convert(value):
if value is not None:
if isinstance(value, list):
return [_afm_convert(x) for x in value]
if isinstance(value, dict):
return {_afm_convert(k): _afm_convert(v)
for k, v in value.items()}
if isinstance(value, str):
return to_text(value)
return value
def module_params_get(module, name):
return _afm_convert(module.params.get(name))
def host_show(module, name):
_args = {
"all": True,
}
try:
_result = ipa_command("host_show", name, _args)
except ipalib_errors.NotFound as e:
msg = str(e)
if "host not found" in msg:
return None
module.fail_json(msg="host_show failed: %s" % msg)
return _result["result"]
def main():
module = AnsibleModule(
argument_spec=dict(
ipaadmin_principal=dict(type="str", default="admin"),
ipaadmin_password=dict(type="str", required=False, no_log=True),
ipaadmin_keytab=dict(type="str", required=False, no_log=False),
hostname=dict(type="str", required=True),
),
mutually_exclusive=[["ipaadmin_password", "ipaadmin_keytab"]],
supports_check_mode=True,
)
if MODULE_IMPORT_ERROR is not None:
module.fail_json(msg=MODULE_IMPORT_ERROR)
# In check mode always return changed.
if module.check_mode:
module.exit_json(changed=True)
ipaadmin_principal = module_params_get(module, "ipaadmin_principal")
ipaadmin_password = module_params_get(module, "ipaadmin_password")
ipaadmin_keytab = module_params_get(module, "ipaadmin_keytab")
if ipaadmin_keytab:
if not os.path.exists(ipaadmin_keytab):
module.fail_json(msg="Unable to open ipaadmin_keytab '%s'" %
ipaadmin_keytab)
hostname = module_params_get(module, "hostname")
exit_args = {}
# Connect to IPA API
with ipa_connect(module, ipaadmin_principal, ipaadmin_password,
ipaadmin_keytab):
res_show = host_show(module, hostname)
args = {"random": True}
if res_show is None:
# Create new host, force is needed to create the host without
# IP address.
args["force"] = True
result = ipa_command("host_add", hostname, args)
else:
# If host exists and has a keytab (is enrolled) then disable the
# host to be able to create a new OTP.
if res_show["has_keytab"]:
ipa_command("host_disable", hostname, {})
result = ipa_command("host_mod", hostname, args)
exit_args["randompassword"] = result['result']['randompassword']
module.exit_json(changed=True, host=exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_ipa_conf.py 0000664 0000000 0000000 00000006053 14600563364 0026330 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_ipa_conf
short_description: Configure ipa.conf
description:
Configure ipa.conf
options:
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: yes
basedn:
description: The basedn of the IPA server (of the form dc=example,dc=com)
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
# Backup and set hostname
- name: Backup and set hostname
ipaclient_ipa_conf:
server: server.example.com
domain: example.com
realm: EXAMPLE.COM
hostname: client1.example.com
basedn: dc=example,dc=com
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports, paths, sysrestore, configure_ipa_conf
)
def main():
module = AnsibleModule(
argument_spec=dict(
domain=dict(required=True, type='str'),
servers=dict(required=True, type='list', elements='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=True, type='str'),
basedn=dict(required=True, type='str'),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
servers = module.params.get('servers')
domain = module.params.get('domain')
realm = module.params.get('realm')
hostname = module.params.get('hostname')
basedn = module.params.get('basedn')
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
configure_ipa_conf(fstore, basedn, realm, domain, servers, hostname)
module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_join.py 0000664 0000000 0000000 00000025655 14600563364 0025522 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_join
short_description:
Join a machine to an IPA realm and get a keytab for the host service
principal
description:
Join a machine to an IPA realm and get a keytab for the host service
principal
options:
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: yes
basedn:
description: The basedn of the IPA server (of the form dc=example,dc=com)
type: str
required: yes
principal:
description:
User Principal allowed to promote replicas and join IPA realm
type: str
required: no
password:
description: Admin user kerberos password
type: str
required: no
keytab:
description: Path to backed up keytab from previous enrollment
type: str
required: no
admin_keytab:
description: The path to a local admin keytab
type: str
required: no
ca_cert_file:
description:
A CA certificate to use. Do not acquire the IPA CA certificate via
automated means
type: str
required: no
force_join:
description: Force client enrollment even if already enrolled
type: bool
required: no
kinit_attempts:
description: Repeat the request for host Kerberos ticket X times
type: int
required: no
default: 5
debug:
description: Turn on extra debugging
type: bool
required: no
krb_name:
description: The krb5 config file name
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
# Join IPA to get the keytab
- name: Join IPA in force mode with maximum 5 kinit attempts
ipaclient_join:
servers: ["server1.example.com","server2.example.com"]
realm: EXAMPLE.COM
basedn: dc=example,dc=com
hostname: client1.example.com
principal: admin
password: MySecretPassword
force_join: yes
kinit_attempts: 5
krb_name: /tmp/tmpkrb5.conf
# Join IPA to get the keytab using ipadiscovery return values
- name: Join IPA
ipaclient_join:
servers: "{{ ipadiscovery.servers }}"
realm: "{{ ipadiscovery.realm }}"
basedn: "{{ ipadiscovery.basedn }}"
hostname: "{{ ipadiscovery.hostname }}"
principal: admin
password: MySecretPassword
krb_name: /tmp/tmpkrb5.conf
'''
RETURN = '''
already_joined:
description: The flag describes if the host is arelady joined.
returned: always
type: bool
'''
import os
import tempfile
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports,
SECURE_PATH, sysrestore, paths, options, realm_to_suffix, kinit_keytab,
GSSError, kinit_password, NUM_VERSION, get_ca_cert, get_ca_certs, errors,
run
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list', elements='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=True, type='str'),
basedn=dict(required=True, type='str'),
principal=dict(required=False, type='str'),
password=dict(required=False, type='str', no_log=True),
keytab=dict(required=False, type='str', no_log=False),
admin_keytab=dict(required=False, type='str', no_log=False),
ca_cert_file=dict(required=False, type='str'),
force_join=dict(required=False, type='bool'),
kinit_attempts=dict(required=False, type='int', default=5),
debug=dict(required=False, type='bool'),
krb_name=dict(required=True, type='str'),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
servers = module.params.get('servers')
realm = module.params.get('realm')
hostname = module.params.get('hostname')
basedn = module.params.get('basedn')
force_join = module.params.get('force_join')
principal = module.params.get('principal')
password = module.params.get('password')
keytab = module.params.get('keytab')
admin_keytab = module.params.get('admin_keytab')
ca_cert_file = module.params.get('ca_cert_file')
kinit_attempts = module.params.get('kinit_attempts')
debug = module.params.get('debug')
krb_name = module.params.get('krb_name')
if password is not None and keytab is not None:
module.fail_json(msg="Password and keytab cannot be used together")
if password is None and admin_keytab is None:
module.fail_json(msg="Password or admin_keytab is needed")
nolog = tuple()
env = {'PATH': SECURE_PATH}
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
host_principal = 'host/%s@%s' % (hostname, realm)
options.ca_cert_file = ca_cert_file
options.principal = principal
options.force = False
options.password = password
ccache_dir = None
changed = False
already_joined = False
try:
env['KRB5_CONFIG'] = krb_name
ccache_dir = tempfile.mkdtemp(prefix='krbcc')
ccache_name = os.path.join(ccache_dir, 'ccache')
join_args = [paths.SBIN_IPA_JOIN,
"-s", servers[0],
"-b", str(realm_to_suffix(realm)),
"-h", hostname]
if debug:
join_args.append("-d")
env['XMLRPC_TRACE_CURL'] = 'yes'
if force_join:
join_args.append("-f")
if principal is not None:
if principal.find('@') == -1:
principal = '%s@%s' % (principal, realm)
if admin_keytab:
join_args.append("-f")
if not os.path.exists(admin_keytab):
module.fail_json(
msg="Keytab file could not be found: %s" %
admin_keytab)
try:
kinit_keytab(principal,
admin_keytab,
ccache_name,
config=krb_name,
attempts=kinit_attempts)
except GSSError as e:
module.fail_json(
msg="Kerberos authentication failed: %s" % str(e))
else:
try:
kinit_password(principal, password, ccache_name,
config=krb_name)
except RuntimeError as e:
module.fail_json(
msg="Kerberos authentication failed: {0}".format(e))
elif keytab:
join_args.append("-f")
if os.path.exists(keytab):
try:
kinit_keytab(host_principal,
keytab,
ccache_name,
config=krb_name,
attempts=kinit_attempts)
except GSSError as e:
module.fail_json(
msg="Kerberos authentication failed: {0}".format(e))
else:
module.fail_json(
msg="Keytab file could not be found: {0}".format(keytab))
elif password:
join_args.append("-w")
join_args.append(password)
nolog = (password,)
env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = ccache_name
# Get the CA certificate
try:
os.environ['KRB5_CONFIG'] = env['KRB5_CONFIG']
if NUM_VERSION < 40100:
get_ca_cert(fstore, options, servers[0], basedn)
else:
get_ca_certs(fstore, options, servers[0], basedn, realm)
os.environ.pop('KRB5_CONFIG', None)
except errors.FileError as e:
module.fail_json(msg='%s' % e)
except Exception as e:
module.fail_json(msg="Cannot obtain CA certificate\n%s" % e)
# Now join the domain
result = run(
join_args, raiseonerr=False, env=env, nolog=nolog,
capture_error=True)
stderr = result.error_output
if result.returncode != 0:
if result.returncode == 13:
already_joined = True
module.log("Host is already joined")
else:
if principal:
run([paths.KDESTROY], raiseonerr=False, env=env)
module.fail_json(msg="Joining realm failed: %s" % stderr)
else:
changed = True
module.log("Enrolled in IPA realm %s" % realm)
# Fail for missing krb5.keytab on already joined host
if already_joined and not os.path.exists(paths.KRB5_KEYTAB):
module.fail_json(msg="krb5.keytab missing! Retry with "
"ipaclient_force_join=yes to generate a new one.")
if principal:
run([paths.KDESTROY], raiseonerr=False, env=env)
# Obtain the TGT. We do it with the temporary krb5.conf, sot
# tha only the KDC we're installing under is contacted.
# Other KDCs might not have replicated the principal yet.
# Once we have the TGT, it's usable on any server.
try:
kinit_keytab(host_principal, paths.KRB5_KEYTAB,
paths.IPA_DNS_CCACHE,
config=krb_name,
attempts=kinit_attempts)
except GSSError as e:
# failure to get ticket makes it impossible to login and
# bind from sssd to LDAP, abort installation
module.fail_json(msg="Failed to obtain host TGT: %s" % e)
finally:
if ccache_dir is not None:
try:
os.rmdir(ccache_dir)
except OSError:
pass
module.exit_json(changed=changed,
already_joined=already_joined)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_set_hostname.py 0000664 0000000 0000000 00000004310 14600563364 0027235 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_set_hostname
short_description: Backup and set hostname
description:
Backup and set hostname
options:
hostname:
description: Fully qualified name of this host
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
# Backup and set hostname
- name: Backup and set hostname
ipaclient_set_hostname:
hostname: client1.example.com
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports, sysrestore, paths, tasks
)
def main():
module = AnsibleModule(
argument_spec=dict(
hostname=dict(required=True, type='str'),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
hostname = module.params.get('hostname')
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)
tasks.backup_hostname(fstore, statestore)
tasks.set_hostname(hostname)
module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_setup_automount.py 0000664 0000000 0000000 00000006352 14600563364 0030027 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_setup_automount
short_description: Setup automount for IPA client
description:
Setup automount for IPA client
options:
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: yes
sssd:
description: The installer sssd setting
type: bool
required: no
default: yes
automount_location:
description: The automount location
type: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
- name: IPA extras configurations
ipaclient_setup_automount:
servers: ["server1.example.com","server2.example.com"]
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports, options, configure_automount, sysrestore,
paths, getargspec
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list', elements='str'),
sssd=dict(required=False, type='bool', default='yes'),
automount_location=dict(required=False, type='str', default=None),
),
supports_check_mode=False,
)
# os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
module._ansible_debug = True
check_imports(module)
setup_logging()
options.servers = module.params.get('servers')
options.server = options.servers
options.sssd = module.params.get('sssd')
options.automount_location = module.params.get('automount_location')
options.location = options.automount_location
changed = False
if options.automount_location:
changed = True
argspec = getargspec(configure_automount)
if len(argspec.args) > 1:
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)
configure_automount(options, statestore)
# Reload the state as automount install may have modified it
fstore._load()
statestore._load()
else:
configure_automount(options)
module.exit_json(changed=changed)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_setup_certmonger.py 0000664 0000000 0000000 00000006523 14600563364 0030141 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_setup_certmonger
short_description: Setup certmonger for IPA client
description: Setup certmonger for IPA client
options:
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: yes
subject_base:
description: |
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
ca_enabled:
description: Whether the Certificate Authority is enabled or not
type: bool
required: yes
request_cert:
description: Request certificate for the machine
type: bool
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
- name: Setup certmonger for IPA client
ipaclient_setup_certmonger:
realm: EXAMPLE.COM
hostname: client1.example.com
subject_base: O=EXAMPLE.COM
ca_enabled: true
request_cert: false
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports,
options, sysrestore, paths, ScriptError, configure_certmonger
)
def main():
module = AnsibleModule(
argument_spec=dict(
realm=dict(required=True, type='str'),
hostname=dict(required=True, type='str'),
subject_base=dict(required=True, type='str'),
ca_enabled=dict(required=True, type='bool'),
request_cert=dict(required=True, type='bool'),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
cli_realm = module.params.get('realm')
hostname = module.params.get('hostname')
subject_base = module.params.get('subject_base')
ca_enabled = module.params.get('ca_enabled')
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
options.request_cert = module.params.get('request_cert')
options.hostname = hostname
try:
configure_certmonger(fstore, subject_base, cli_realm, hostname,
options, ca_enabled)
except ScriptError as e:
module.fail_json(msg=str(e))
module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_setup_firefox.py 0000664 0000000 0000000 00000004731 14600563364 0027435 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_setup_firefox
short_description: Setup firefox for IPA client
description:
Setup firefox for IPA client
options:
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
firefox_dir:
description:
Specify directory where Firefox is installed (for example
'/usr/lib/firefox')
type: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
- name: Setup firefox for IPA client
ipaclient_setup_firefox:
servers: ["server1.example.com","server2.example.com"]
domain: example.com
firefox_dir: /usr/lib/firefox
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports, sysrestore, paths, options, configure_firefox
)
def main():
module = AnsibleModule(
argument_spec=dict(
domain=dict(required=True, type='str'),
firefox_dir=dict(required=False, type='str'),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
domain = module.params.get('domain')
options.firefox_dir = module.params.get('firefox_dir')
statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)
configure_firefox(options, statestore, domain)
module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_setup_krb5.py 0000664 0000000 0000000 00000011626 14600563364 0026637 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_setup_krb5
short_description: Setup krb5 for IPA client
description:
Setup krb5 for IPA client
options:
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: no
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: no
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: no
hostname:
description: Fully qualified name of this host
type: str
required: no
kdc:
description: The name or address of the host running the KDC
type: str
required: no
dnsok:
description: The installer dnsok setting
type: bool
required: no
default: no
client_domain:
description: Primary DNS domain of the IPA deployment
type: str
required: no
sssd:
description: The installer sssd setting
type: bool
required: no
default: no
force:
description: Installer force parameter
type: bool
required: no
default: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
# Backup and set hostname
- name: Backup and set hostname
ipaclient_setup_krb5:
server:
domain:
realm:
hostname: client1.example.com
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports, sysrestore, paths, configure_krb5_conf,
logger
)
def main():
module = AnsibleModule(
argument_spec=dict(
domain=dict(required=False, type='str', default=None),
servers=dict(required=False, type='list', elements='str',
default=None),
realm=dict(required=False, type='str', default=None),
hostname=dict(required=False, type='str', default=None),
kdc=dict(required=False, type='str', default=None),
dnsok=dict(required=False, type='bool', default=False),
client_domain=dict(required=False, type='str', default=None),
sssd=dict(required=False, type='bool', default=False),
force=dict(required=False, type='bool', default=False),
# on_master=dict(required=False, type='bool', default=False),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
servers = module.params.get('servers')
domain = module.params.get('domain')
realm = module.params.get('realm')
hostname = module.params.get('hostname')
kdc = module.params.get('kdc')
dnsok = module.params.get('dnsok')
client_domain = module.params.get('client_domain')
sssd = module.params.get('sssd')
force = module.params.get('force')
# on_master = module.params.get('on_master')
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
# if options.on_master:
# # If on master assume kerberos is already configured properly.
# # Get the host TGT.
# try:
# kinit_keytab(host_principal, paths.KRB5_KEYTAB, CCACHE_FILE,
# attempts=options.kinit_attempts)
# os.environ['KRB5CCNAME'] = CCACHE_FILE
# except gssapi.exceptions.GSSError as e:
# logger.error("Failed to obtain host TGT: %s", e)
# raise ScriptError(rval=CLIENT_INSTALL_ERROR)
# else:
# Configure krb5.conf
fstore.backup_file(paths.KRB5_CONF)
configure_krb5_conf(
cli_realm=realm,
cli_domain=domain,
cli_server=servers,
cli_kdc=kdc,
dnsok=dnsok,
filename=paths.KRB5_CONF,
client_domain=client_domain,
client_hostname=hostname,
configure_sssd=sssd,
force=force)
logger.info(
"Configured /etc/krb5.conf for IPA realm %s", realm)
module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_setup_nis.py 0000664 0000000 0000000 00000005163 14600563364 0026564 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_setup_nis
short_description: Setup NIS for IPA client
description:
Setup NIS for IPA client
options:
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
nisdomain:
description: The NIS domain name
type: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
- name: Setup NIS for IPA client
ipaclient_setup_nis:
domain: example.com
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports, options, sysrestore, paths,
configure_nisdomain, getargspec
)
def main():
module = AnsibleModule(
argument_spec=dict(
domain=dict(required=True, type='str'),
nisdomain=dict(required=False, type='str'),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
domain = module.params.get('domain')
options.nisdomain = module.params.get('nisdomain')
statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)
# pylint: disable=deprecated-method
argspec = getargspec(configure_nisdomain)
# pylint: enable=deprecated-method
if "statestore" not in argspec.args:
# NUM_VERSION < 40500:
configure_nisdomain(options=options, domain=domain)
else:
configure_nisdomain(options=options, domain=domain,
statestore=statestore)
module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_setup_nss.py 0000664 0000000 0000000 00000051133 14600563364 0026574 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_setup_nss
short_description: Create IPA client NSS database
description: Create IPA NSS database
options:
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: yes
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: yes
basedn:
description: The basedn of the IPA server (of the form dc=example,dc=com)
type: str
required: yes
principal:
description:
User Principal allowed to promote replicas and join IPA realm
type: str
required: no
subject_base:
description: |
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
ca_enabled:
description: Whether the Certificate Authority is enabled or not
type: bool
required: yes
mkhomedir:
description: Create home directories for users on their first login
type: bool
required: no
on_master:
description: Whether the configuration is done on the master or not
type: bool
required: no
dnsok:
description: The installer dnsok setting
type: bool
required: no
default: no
enable_dns_updates:
description: |
Configures the machine to attempt dns updates when the ip address
changes
type: bool
required: no
all_ip_addresses:
description: |
All routable IP addresses configured on any interface will be added
to DNS
type: bool
required: no
default: no
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
request_cert:
description: Request certificate for the machine
type: bool
required: no
default: no
preserve_sssd:
description: Preserve old SSSD configuration if possible
type: bool
required: no
no_ssh:
description: Do not configure OpenSSH client
type: bool
required: no
no_sshd:
description: Do not configure OpenSSH server
type: bool
required: no
no_sudo:
description: Do not configure SSSD as data source for sudo
type: bool
required: no
subid:
description: Configure SSSD as data source for subid
type: bool
required: no
fixed_primary:
description: Configure sssd to use fixed server as primary IPA server
type: bool
required: no
permit:
description: Disable access rules by default, permit all access
type: bool
required: no
no_krb5_offline_passwords:
description:
Configure SSSD not to store user password when the server is offline
type: bool
required: no
no_dns_sshfp:
description: Do not automatically create DNS SSHFP records
type: bool
required: no
default: no
nosssd_files:
description: >
The dist of nss_ldap or nss-pam-ldapd files if sssd is disabled
required: yes
type: dict
selinux_works:
description: True if selinux status check passed
required: false
type: bool
krb_name:
description: The krb5 config file name
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
- name: Create IPA client NSS database
ipaclient_setup_nss:
servers: ["server1.example.com","server2.example.com"]
domain: example.com
realm: EXAMPLE.COM
basedn: dc=example,dc=com
hostname: client1.example.com
subject_base: O=EXAMPLE.COM
principal: admin
ca_enabled: yes
krb_name: /tmp/tmpkrb5.conf
'''
RETURN = '''
'''
import os
import time
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports,
options, sysrestore, paths, ansible_module_get_parsed_ip_addresses,
api, errors, create_ipa_nssdb, ipautil, ScriptError, CLIENT_INSTALL_ERROR,
get_certs_from_ldap, DN, certstore, x509, logger, certdb,
CalledProcessError, tasks, client_dns, services,
update_ssh_keys, save_state, configure_ldap_conf, configure_nslcd_conf,
configure_openldap_conf, hardcode_ldap_server, getargspec, NUM_VERSION,
serialization, configure_selinux_for_client
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list', elements='str'),
domain=dict(required=True, type='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=True, type='str'),
basedn=dict(required=True, type='str'),
principal=dict(required=False, type='str'),
subject_base=dict(required=True, type='str'),
ca_enabled=dict(required=True, type='bool'),
mkhomedir=dict(required=False, type='bool'),
on_master=dict(required=False, type='bool'),
dnsok=dict(required=False, type='bool', default=False),
enable_dns_updates=dict(required=False, type='bool'),
all_ip_addresses=dict(required=False, type='bool', default=False),
ip_addresses=dict(required=False, type='list', elements='str',
default=None),
request_cert=dict(required=False, type='bool', default=False),
preserve_sssd=dict(required=False, type='bool'),
no_ssh=dict(required=False, type='bool'),
no_sshd=dict(required=False, type='bool'),
no_sudo=dict(required=False, type='bool'),
subid=dict(required=False, type='bool'),
fixed_primary=dict(required=False, type='bool'),
permit=dict(required=False, type='bool'),
no_krb5_offline_passwords=dict(required=False, type='bool'),
no_dns_sshfp=dict(required=False, type='bool', default=False),
nosssd_files=dict(required=True, type='dict'),
krb_name=dict(required=True, type='str'),
selinux_works=dict(required=False, type='bool', default=False),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
cli_server = module.params.get('servers')
cli_realm = module.params.get('realm')
hostname = module.params.get('hostname')
cli_basedn = module.params.get('basedn')
cli_domain = module.params.get('domain')
options.principal = module.params.get('principal')
subject_base = module.params.get('subject_base')
ca_enabled = module.params.get('ca_enabled')
options.mkhomedir = module.params.get('mkhomedir')
options.on_master = module.params.get('on_master')
dnsok = module.params.get('dnsok')
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)
os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
options.dns_updates = module.params.get('enable_dns_updates')
options.all_ip_addresses = module.params.get('all_ip_addresses')
options.ip_addresses = ansible_module_get_parsed_ip_addresses(module)
options.request_cert = module.params.get('request_cert')
options.hostname = hostname
options.host_name = hostname
options.preserve_sssd = module.params.get('preserve_sssd')
options.no_ssh = module.params.get('no_ssh')
options.conf_ssh = not options.no_ssh
options.no_sshd = module.params.get('no_sshd')
options.conf_sshd = not options.no_sshd
options.no_sudo = module.params.get('no_sudo')
options.conf_sudo = not options.no_sudo
options.subid = module.params.get('subid')
options.primary = module.params.get('fixed_primary')
options.permit = module.params.get('permit')
options.no_krb5_offline_passwords = module.params.get(
'no_krb5_offline_passwords')
options.krb5_offline_passwords = not options.no_krb5_offline_passwords
options.no_dns_sshfp = module.params.get('no_dns_sshfp')
options.create_sshfp = not options.no_dns_sshfp
options.no_sssd = False
options.sssd = not options.no_sssd
options.no_ac = False
nosssd_files = module.params.get('nosssd_files')
selinux_works = module.params.get('selinux_works')
krb_name = module.params.get('krb_name')
os.environ['KRB5_CONFIG'] = krb_name
# pylint: disable=invalid-name
CCACHE_FILE = paths.IPA_DNS_CCACHE
api.bootstrap(context='cli_installer',
confdir=paths.ETC_IPA,
debug=False,
delegate=False)
api.finalize()
api.Backend.rpcclient.connect()
try:
api.Backend.rpcclient.forward('ping')
except errors.KerberosError:
# Cannot connect to the server due to Kerberos error, trying with
# delegate=True
api.Backend.rpcclient.disconnect()
api.Backend.rpcclient.connect(delegate=True)
api.Backend.rpcclient.forward('ping')
##########################################################################
try:
# Create IPA NSS database
try:
create_ipa_nssdb()
except ipautil.CalledProcessError as e:
raise ScriptError(
"Failed to create IPA NSS database: %s" % e,
rval=CLIENT_INSTALL_ERROR)
# Get CA certificates from the certificate store
try:
ca_certs = get_certs_from_ldap(cli_server[0], cli_basedn,
cli_realm, ca_enabled)
except errors.NoCertificateError:
if ca_enabled:
ca_subject = DN(('CN', 'Certificate Authority'), subject_base)
else:
ca_subject = None
# Set ca_certs
# Copied from ipaclient_api
ca_certs = x509.load_certificate_list_from_file(paths.IPA_CA_CRT)
if 40500 <= NUM_VERSION < 40590:
ca_certs = [cert.public_bytes(serialization.Encoding.DER)
for cert in ca_certs]
elif NUM_VERSION < 40500:
ca_certs = [cert.der_data for cert in ca_certs]
# Copied from ipaclient_api
ca_certs = certstore.make_compat_ca_certs(ca_certs, cli_realm,
ca_subject)
ca_certs_trust = [(c, n,
certstore.key_policy_to_trust_flags(t, True, u))
for (c, n, t, u) in ca_certs]
if hasattr(paths, "KDC_CA_BUNDLE_PEM"):
x509.write_certificate_list(
[c for c, n, t, u in ca_certs if t is not False],
paths.KDC_CA_BUNDLE_PEM,
# mode=0o644
)
if hasattr(paths, "CA_BUNDLE_PEM"):
x509.write_certificate_list(
[c for c, n, t, u in ca_certs if t is not False],
paths.CA_BUNDLE_PEM,
# mode=0o644
)
# Add the CA certificates to the IPA NSS database
logger.debug("Adding CA certificates to the IPA NSS database.")
ipa_db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR)
for cert, nickname, trust_flags in ca_certs_trust:
try:
ipa_db.add_cert(cert, nickname, trust_flags)
except CalledProcessError:
raise ScriptError(
"Failed to add %s to the IPA NSS database." % nickname,
rval=CLIENT_INSTALL_ERROR)
# Add the CA certificates to the platform-dependant systemwide CA
# store
tasks.insert_ca_certs_into_systemwide_ca_store(ca_certs)
if not options.on_master:
client_dns(cli_server[0], hostname, options)
if hasattr(paths, "SSH_CONFIG_DIR"):
ssh_config_dir = paths.SSH_CONFIG_DIR
else:
ssh_config_dir = services.knownservices.sshd.get_config_dir()
update_ssh_keys(hostname, ssh_config_dir, options.create_sshfp)
try:
os.remove(CCACHE_FILE)
except Exception:
pass
# pylint: disable=deprecated-method
argspec_save_state = getargspec(save_state)
# Name Server Caching Daemon. Disable for SSSD, use otherwise
# (if installed)
nscd = services.knownservices.nscd
if nscd.is_installed():
if "statestore" in argspec_save_state.args:
save_state(nscd, statestore)
else:
save_state(nscd)
nscd_service_action = None
try:
if options.sssd:
nscd_service_action = 'stop'
nscd.stop()
else:
nscd_service_action = 'restart'
nscd.restart()
except Exception:
logger.warning(
"Failed to %s the %s daemon",
nscd_service_action, nscd.service_name)
if not options.sssd:
logger.warning(
"Caching of users/groups will not be available")
try:
if options.sssd:
nscd.disable()
else:
nscd.enable()
except Exception:
if not options.sssd:
logger.warning(
"Failed to configure automatic startup of the %s "
"daemon",
nscd.service_name)
logger.info(
"Caching of users/groups will not be "
"available after reboot")
else:
logger.warning(
"Failed to disable %s daemon. Disable it manually.",
nscd.service_name)
else:
# this is optional service, just log
if not options.sssd:
logger.info(
"%s daemon is not installed, skip configuration",
nscd.service_name)
nslcd = services.knownservices.nslcd
if nslcd.is_installed():
if "statestore" in argspec_save_state.args:
save_state(nslcd, statestore)
else:
save_state(nslcd)
retcode, conf = (0, None)
if not options.no_ac:
# Modify nsswitch/pam stack
# pylint: disable=deprecated-method
argspec = getargspec(tasks.modify_nsswitch_pam_stack)
the_options = {
"sssd": options.sssd,
"mkhomedir": options.mkhomedir,
"statestore": statestore,
}
if "sudo" in argspec.args:
the_options["sudo"] = options.conf_sudo
if "subid" in argspec.args:
the_options["subid"] = options.subid
tasks.modify_nsswitch_pam_stack(**the_options)
if hasattr(paths, "AUTHSELECT") and paths.AUTHSELECT is not None:
# authselect is used
# if mkhomedir, make sure oddjobd is enabled and started
if options.mkhomedir:
oddjobd = services.service('oddjobd', api)
running = oddjobd.is_running()
enabled = oddjobd.is_enabled()
statestore.backup_state('oddjobd', 'running', running)
statestore.backup_state('oddjobd', 'enabled', enabled)
try:
if not enabled:
oddjobd.enable()
if not running:
oddjobd.start()
except Exception as e:
logger.critical("Unable to start oddjobd: %s", str(e))
logger.info("%s enabled", "SSSD" if options.sssd else "LDAP")
if options.sssd:
if selinux_works and configure_selinux_for_client is not None:
configure_selinux_for_client(statestore)
sssd = services.service('sssd', api)
try:
sssd.restart()
except CalledProcessError:
logger.warning("SSSD service restart was unsuccessful.")
try:
sssd.enable()
except CalledProcessError as e:
logger.warning(
"Failed to enable automatic startup of the SSSD "
"daemon: %s", e)
if not options.sssd:
tasks.modify_pam_to_use_krb5(statestore)
logger.info("Kerberos 5 enabled")
# Update non-SSSD LDAP configuration after authconfig calls as it
# would change its configuration otherways
if not options.sssd:
for configurer in [configure_ldap_conf, configure_nslcd_conf]:
(retcode, conf, filenames) = configurer(
fstore, cli_basedn, cli_realm,
cli_domain, cli_server, dnsok,
options, nosssd_files[configurer.__name__])
if retcode:
raise ScriptError(rval=CLIENT_INSTALL_ERROR)
if conf:
logger.info(
"%s configured using configuration file(s) %s",
conf, filenames)
if configure_openldap_conf(fstore, cli_basedn, cli_server):
logger.info("Configured /etc/openldap/ldap.conf")
else:
logger.info("Failed to configure /etc/openldap/ldap.conf")
# Check that nss is working properly
if not options.on_master:
user = options.principal
if user is None:
user = "admin@%s" % cli_domain
logger.info("Principal is not set when enrolling with OTP"
"; using principal '%s' for 'getent passwd'",
user)
elif '@' not in user:
user = "%s@%s" % (user, cli_domain)
n = 0
found = False
# Loop for up to 10 seconds to see if nss is working properly.
# It can sometimes take a few seconds to connect to the remote
# provider.
# Particulary, SSSD might take longer than 6-8 seconds.
if hasattr(paths, "GETENT"):
getent_cmd = paths.GETENT
else:
getent_cmd = '/usr/bin/getent'
while n < 10 and not found:
try:
ipautil.run([getent_cmd, "passwd", user])
found = True
except Exception:
time.sleep(1)
n = n + 1
if not found:
logger.error("Unable to find '%s' user with 'getent "
"passwd %s'!", user.split("@")[0], user)
if conf:
logger.info("Recognized configuration: %s", conf)
else:
logger.error(
"Unable to reliably detect "
"configuration. Check NSS setup manually.")
try:
hardcode_ldap_server(cli_server)
except Exception as e:
logger.error(
"Adding hardcoded server name to "
"/etc/ldap.conf failed: %s", str(e))
except ScriptError as e:
module.fail_json(msg=str(e))
##########################################################################
module.exit_json(changed=True,
ca_enabled_ra=ca_enabled)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_setup_ntp.py 0000664 0000000 0000000 00000014123 14600563364 0026570 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_setup_ntp
short_description: Setup NTP for IPA client
description:
Setup NTP for IPA client
options:
ntp_servers:
description: ntp servers to use
type: list
elements: str
required: no
ntp_pool:
description: ntp server pool to use
type: str
required: no
no_ntp:
description: Do not configure ntp
type: bool
required: no
default: no
on_master:
description: Whether the configuration is done on the master or not
type: bool
required: no
default: no
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: no
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports,
options, sysrestore, paths, sync_time, logger, ipadiscovery,
timeconf, getargspec
)
def main():
module = AnsibleModule(
argument_spec=dict(
# basic
ntp_servers=dict(required=False, type='list', elements='str',
default=None),
ntp_pool=dict(required=False, type='str', default=None),
no_ntp=dict(required=False, type='bool', default=False),
# force_ntpd=dict(required=False, type='bool', default=False),
on_master=dict(required=False, type='bool', default=False),
# additional
servers=dict(required=False, type='list', elements='str',
default=None),
domain=dict(required=False, type='str', default=None),
),
supports_check_mode=False,
)
# module._ansible_debug = True
check_imports(module)
setup_logging()
options.ntp_servers = module.params.get('ntp_servers')
options.ntp_pool = module.params.get('ntp_pool')
options.no_ntp = module.params.get('no_ntp')
# options.force_ntpd = module.params.get('force_ntpd')
options.on_master = module.params.get('on_master')
cli_server = module.params.get('servers')
cli_domain = module.params.get('domain')
options.conf_ntp = not options.no_ntp
options.debug = False
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)
synced_ntp = False
if sync_time is not None:
if options.conf_ntp:
# Attempt to configure and sync time with NTP server (chrony).
# pylint: disable=deprecated-method
argspec = getargspec(sync_time)
# pylint: enable=deprecated-method
if "options" not in argspec.args:
synced_ntp = sync_time(options.ntp_servers, options.ntp_pool,
fstore, statestore)
else:
synced_ntp = sync_time(options, fstore, statestore)
elif options.on_master:
# If we're on master skipping the time sync here because it was
# done in ipa-server-install
logger.info(
"Skipping attempt to configure and synchronize time with"
" chrony server as it has been already done on master.")
else:
logger.info("Skipping chrony configuration")
else:
ntp_srv_servers = []
if not options.on_master and options.conf_ntp:
# Attempt to sync time with IPA server.
# If we're skipping NTP configuration, we also skip the time sync
# here.
# We assume that NTP servers are discoverable through SRV records
# in the DNS.
# If that fails, we try to sync directly with IPA server,
# assuming it runs NTP
logger.info('Synchronizing time with KDC...')
ds = ipadiscovery.IPADiscovery()
ntp_srv_servers = ds.ipadns_search_srv(cli_domain, '_ntp._udp',
None, break_on_first=False)
synced_ntp = False
ntp_servers = ntp_srv_servers
# use user specified NTP servers if there are any
if options.ntp_servers:
ntp_servers = options.ntp_servers
for _ntp_server in ntp_servers:
synced_ntp = timeconf.synconce_ntp(_ntp_server, options.debug)
if synced_ntp:
break
if not synced_ntp and not options.ntp_servers:
synced_ntp = timeconf.synconce_ntp(cli_server[0],
options.debug)
if not synced_ntp:
module.warn(
"Unable to sync time with NTP "
"server, assuming the time is in sync. Please check "
"that 123 UDP port is opened.")
else:
logger.info('Skipping synchronizing time with NTP server.')
# Done
module.exit_json(changed=synced_ntp)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_setup_ssh.py 0000664 0000000 0000000 00000007031 14600563364 0026564 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_setup_ssh
short_description: Configure ssh and sshd for IPA client
description:
Configure ssh and sshd for IPA client
options:
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: yes
no_ssh:
description: Do not configure OpenSSH client
type: bool
required: no
default: no
ssh_trust_dns:
description: Configure OpenSSH client to trust DNS SSHFP records
type: bool
required: no
default: no
no_sshd:
description: Do not configure OpenSSH server
type: bool
required: no
default: no
sssd:
description: The installer sssd setting
type: bool
required: no
default: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
- name: Configure ssh and sshd for IPA client
ipaclient_setup_ssh:
servers: ["server1.example.com","server2.example.com"]
ssh: yes
sshd: yes
sssd: yes
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports,
options, sysrestore, paths, configure_ssh_config, configure_sshd_config
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list', elements='str'),
no_ssh=dict(required=False, type='bool', default='no'),
ssh_trust_dns=dict(required=False, type='bool', default='no'),
no_sshd=dict(required=False, type='bool', default='no'),
sssd=dict(required=False, type='bool', default='no'),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
options.servers = module.params.get('servers')
options.server = options.servers
options.no_ssh = module.params.get('no_ssh')
options.conf_ssh = not options.no_ssh
options.trust_sshfp = module.params.get('ssh_trust_dns')
options.no_sshd = module.params.get('no_sshd')
options.conf_sshd = not options.no_sshd
options.sssd = module.params.get('sssd')
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
# os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
changed = False
if options.conf_ssh:
configure_ssh_config(fstore, options)
changed = True
if options.conf_sshd:
configure_sshd_config(fstore, options)
changed = True
module.exit_json(changed=changed)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_setup_sssd.py 0000664 0000000 0000000 00000013402 14600563364 0026742 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_setup_sssd
short_description: Setup sssd for IPA client
description:
Setup sssd for IPA client
options:
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: yes
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: yes
on_master:
description: Whether the configuration is done on the master or not
type: bool
required: no
no_ssh:
description: Do not configure OpenSSH client
type: bool
required: no
no_sshd:
description: Do not configure OpenSSH server
type: bool
required: no
no_sudo:
description: Do not configure SSSD as data source for sudo
type: bool
required: no
all_ip_addresses:
description:
All routable IP addresses configured on any interface will be added
to DNS
type: bool
required: no
fixed_primary:
description: Configure sssd to use fixed server as primary IPA server
type: bool
required: no
permit:
description: Disable access rules by default, permit all access
type: bool
required: no
enable_dns_updates:
description:
Configures the machine to attempt dns updates when the ip address
changes
type: bool
required: no
preserve_sssd:
description: Preserve old SSSD configuration if possible
type: bool
required: no
no_krb5_offline_passwords:
description:
Configure SSSD not to store user password when the server is offline
type: bool
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
- name: Configure SSSD
ipaclient_setup_sssd:
servers: ["server1.example.com","server2.example.com"]
domain: example.com
realm: EXAMPLE.COM
hostname: client1.example.com
no_krb5_offline_passwords: yes
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports, options, sysrestore, paths,
configure_sssd_conf, logger
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list', elements='str'),
domain=dict(required=True, type='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=True, type='str'),
on_master=dict(required=False, type='bool'),
no_ssh=dict(required=False, type='bool'),
no_sshd=dict(required=False, type='bool'),
no_sudo=dict(required=False, type='bool'),
all_ip_addresses=dict(required=False, type='bool'),
fixed_primary=dict(required=False, type='bool'),
permit=dict(required=False, type='bool'),
enable_dns_updates=dict(required=False, type='bool'),
preserve_sssd=dict(required=False, type='bool'),
no_krb5_offline_passwords=dict(required=False, type='bool'),
),
supports_check_mode=False,
)
# ansible_log = AnsibleModuleLog(module, logger)
# options.set_logger(ansible_log)
module._ansible_debug = True
check_imports(module)
setup_logging()
cli_server = module.params.get('servers')
cli_domain = module.params.get('domain')
cli_realm = module.params.get('realm')
hostname = module.params.get('hostname')
options.on_master = module.params.get('on_master')
options.no_ssh = module.params.get('no_ssh')
options.conf_ssh = not options.no_ssh
options.no_sshd = module.params.get('no_sshd')
options.conf_sshd = not options.no_sshd
options.no_sudo = module.params.get('no_sudo')
options.conf_sudo = not options.no_sudo
options.all_ip_addresses = module.params.get('all_ip_addresses')
options.primary = module.params.get('fixed_primary')
options.permit = module.params.get('permit')
options.dns_updates = module.params.get('enable_dns_updates')
options.preserve_sssd = module.params.get('preserve_sssd')
options.no_krb5_offline_passwords = module.params.get(
'no_krb5_offline_passwords')
options.krb5_offline_passwords = not options.no_krb5_offline_passwords
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
client_domain = hostname[hostname.find(".") + 1:]
if configure_sssd_conf(fstore, cli_realm, cli_domain, cli_server,
options, client_domain, hostname):
module.fail_json("configure_sssd_conf failed")
logger.info("Configured /etc/sssd/sssd.conf")
module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_temp_krb5.py 0000664 0000000 0000000 00000010744 14600563364 0026444 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_temp_krb5
short_description:
Create temporary krb5 configuration.
description:
Create temporary krb5 configuration for deferring the creation of the final
krb5.conf on clients
options:
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: yes
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: yes
kdc:
description: The name or address of the host running the KDC
type: str
required: yes
on_master:
description: Whether the configuration is done on the master or not
type: bool
required: no
default: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
# Test IPA with local keytab
- name: Test IPA in force mode with maximum 5 kinit attempts
ipaclient_test_keytab:
servers: ["server1.example.com","server2.example.com"]
domain: example.com
realm: EXAMPLE.COM
kdc: server1.example.com
hostname: client1.example.com
# Test IPA with ipadiscovery return values
- name: Join IPA
ipaclient_test_keytab:
servers: "{{ ipadiscovery.servers }}"
domain: "{{ ipadiscovery.domain }}"
realm: "{{ ipadiscovery.realm }}"
kdc: "{{ ipadiscovery.kdc }}"
hostname: "{{ ipadiscovery.hostname }}"
'''
RETURN = '''
krb_name:
description: The krb5 config file name
returned: always
type: str
'''
import os
import tempfile
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports, configure_krb5_conf
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list', elements='str'),
domain=dict(required=True, type='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=True, type='str'),
kdc=dict(required=True, type='str'),
on_master=dict(required=False, type='bool', default=False),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
servers = module.params.get('servers')
domain = module.params.get('domain')
realm = module.params.get('realm')
hostname = module.params.get('hostname')
kdc = module.params.get('kdc')
client_domain = hostname[hostname.find(".") + 1:]
krb_name = None
# Create temporary krb5 configuration
try:
(krb_fd, krb_name) = tempfile.mkstemp()
os.close(krb_fd)
configure_krb5_conf(
cli_realm=realm,
cli_domain=domain,
cli_server=servers,
cli_kdc=kdc,
dnsok=False,
filename=krb_name,
client_domain=client_domain,
client_hostname=hostname,
configure_sssd=True,
force=False)
except Exception as ex:
if krb_name:
try:
os.remove(krb_name)
except OSError:
module.fail_json(msg="Could not remove %s" % krb_name)
module.fail_json(
msg="Failed to create temporary krb5 configuration: %s" % str(ex))
module.exit_json(changed=False,
krb_name=krb_name)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_test.py 0000664 0000000 0000000 00000105655 14600563364 0025541 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_test
short_description: Tries to discover IPA server
description:
Tries to discover IPA server using DNS or host name
options:
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: no
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: no
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: no
hostname:
description: Fully qualified name of this host
type: str
required: no
ntp_servers:
description: ntp servers to use
type: list
elements: str
required: no
ntp_pool:
description: ntp server pool to use
type: str
required: no
no_ntp:
description: Do not configure ntp
type: bool
required: no
default: no
force_ntpd:
description:
Stop and disable any time&date synchronization services besides ntpd
Deprecated since 4.7
type: bool
required: no
default: no
nisdomain:
description: The NIS domain name
type: str
required: no
no_nisdomain:
description: Do not configure NIS domain name
type: bool
required: no
default: no
kinit_attempts:
description: Repeat the request for host Kerberos ticket X times
type: int
required: no
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
type: list
elements: str
required: no
configure_firefox:
description: Configure Firefox to use IPA domain credentials
type: bool
required: no
default: no
firefox_dir:
description:
Specify directory where Firefox is installed (for example
'/usr/lib/firefox')
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
all_ip_addresses:
description:
All routable IP addresses configured on any interface will be added
to DNS
type: bool
required: no
default: no
on_master:
description: Whether the configuration is done on the master or not
type: bool
required: no
default: no
enable_dns_updates:
description:
Configures the machine to attempt dns updates when the ip address
changes
type: bool
required: no
default: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
# Complete autodiscovery, register return values as ipaclient_test
- name: IPA discovery
ipaclient_test:
register: register_ipaclient_test
# Discovery using servers, register return values as ipaclient_test
- name: IPA discovery
ipaclient_test:
servers: server1.domain.com,server2.domain.com
register: register_ipaclient_test
# Discovery using domain name, register return values as ipaclient_test
- name: IPA discovery
ipaclient_test:
domain: domain.com
register: register_ipaclient_test
# Discovery using realm, register return values as ipaclient_test
- name: IPA discovery
ipaclient_test:
realm: DOMAIN.COM
register: register_ipaclient_test
# Discovery using hostname, register return values as ipaclient_test
- name: IPA discovery
ipaclient_test:
hostname: host.domain.com
register: register_ipaclient_test
'''
RETURN = '''
servers:
description: The list of detected or passed in IPA servers.
returned: always
type: list
elements: str
sample: ["server1.example.com","server2.example.com"]
domain:
description: The DNS domain of the detected or passed in IPA deployment.
returned: always
type: str
sample: example.com
realm:
description: The Kerberos realm of the detected or passed in IPA deployment.
returned: always
type: str
sample: EXAMPLE.COM
kdc:
description: The detected KDC server name.
returned: always
type: str
sample: server1.example.com
basedn:
description: The basedn of the detected IPA server.
returned: always
type: str
sample: dc=example,dc=com
hostname:
description: The detected or passed in FQDN hostname of the client.
returned: always
type: str
sample: client1.example.com
client_domain:
description: The domain name of the client.
returned: always
type: str
sample: example.com
dnsok:
description: True if DNS discovery worked and not passed in any servers.
returned: always
type: bool
ntp_servers:
description: The list of detected NTP servers.
returned: always
type: list
elements: str
sample: ["ntp.example.com"]
ipa_python_version:
description: >
The IPA python version as a number:
*10000+*100+
returned: always
type: int
sample: 040400
nosssd_files:
description: >
The dist of nss_ldap or nss-pam-ldapd files if sssd is disabled
returned: always
type: list
elements: str
selinux_works:
description: True if the selinux status check passed.
returned: always
type: bool
'''
import os
import socket
try:
from ansible.module_utils.six.moves.configparser import RawConfigParser
except ImportError:
from ConfigParser import RawConfigParser
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports,
paths, sysrestore, options, CheckedIPAddress, validate_domain_name,
logger, x509, normalize_hostname, installer, version, ScriptError,
CLIENT_INSTALL_ERROR, tasks, check_ldap_conf, timeconf, constants,
validate_hostname, nssldap_exists, gssapi, remove_file,
check_ip_addresses, ipadiscovery, print_port_conf_info,
IPA_PYTHON_VERSION, getargspec
)
def get_cert_path(cert_path):
"""
If a CA certificate is passed in on the command line, use that.
Else if a CA file exists in paths.IPA_CA_CRT then use that.
Otherwise return None.
"""
if cert_path is not None:
return cert_path
if os.path.exists(paths.IPA_CA_CRT):
return paths.IPA_CA_CRT
return None
def is_client_configured():
"""
Check if ipa client is configured.
IPA client is configured when /etc/ipa/default.conf exists and
/var/lib/ipa-client/sysrestore/sysrestore.state exists.
:returns: boolean
"""
return (os.path.isfile(paths.IPA_DEFAULT_CONF) and
os.path.isfile(os.path.join(paths.IPA_CLIENT_SYSRESTORE,
sysrestore.SYSRESTORE_STATEFILE)))
def get_ipa_conf():
"""
Return IPA configuration read from `/etc/ipa/default.conf`.
:returns: dict containing key,value
"""
parser = RawConfigParser()
parser.read(paths.IPA_DEFAULT_CONF)
result = {}
for item in ['basedn', 'realm', 'domain', 'server', 'host', 'xmlrpc_uri']:
if parser.has_option('global', item):
value = parser.get('global', item)
else:
value = None
if value:
result[item] = value
return result
def main():
module = AnsibleModule(
argument_spec=dict(
# basic
domain=dict(required=False, type='str', default=None),
servers=dict(required=False, type='list', elements='str',
default=None),
realm=dict(required=False, type='str', default=None),
hostname=dict(required=False, type='str', default=None),
ntp_servers=dict(required=False, type='list', elements='str',
default=None),
ntp_pool=dict(required=False, type='str', default=None),
no_ntp=dict(required=False, type='bool', default=False),
force_ntpd=dict(required=False, type='bool', default=False),
nisdomain=dict(required=False, type='str', default=None),
no_nisdomain=dict(required=False, type='bool', default='no'),
kinit_attempts=dict(required=False, type='int'),
ca_cert_files=dict(required=False, type='list', elements='str',
default=None),
configure_firefox=dict(required=False, type='bool', default=False),
firefox_dir=dict(required=False, type='str'),
ip_addresses=dict(required=False, type='list', elements='str',
default=None),
all_ip_addresses=dict(required=False, type='bool', default=False),
on_master=dict(required=False, type='bool', default=False),
# sssd
enable_dns_updates=dict(required=False, type='bool',
default=False),
),
supports_check_mode=False,
)
# module._ansible_debug = True
check_imports(module)
setup_logging()
options.domain_name = module.params.get('domain')
options.servers = module.params.get('servers')
options.realm_name = module.params.get('realm')
options.host_name = module.params.get('hostname')
options.ntp_servers = module.params.get('ntp_servers')
options.ntp_pool = module.params.get('ntp_pool')
options.no_ntp = module.params.get('no_ntp')
options.force_ntpd = module.params.get('force_ntpd')
options.nisdomain = module.params.get('nisdomain')
options.no_nisdomain = module.params.get('no_nisdomain')
options.kinit_attempts = module.params.get('kinit_attempts')
options.ca_cert_files = module.params.get('ca_cert_files')
options.configure_firefox = module.params.get('configure_firefox')
options.firefox_dir = module.params.get('firefox_dir')
options.ip_addresses = module.params.get('ip_addresses')
options.all_ip_addresses = module.params.get('all_ip_addresses')
options.on_master = module.params.get('on_master')
options.enable_dns_updates = module.params.get('enable_dns_updates')
# Get domain from first server if domain is not set, but if there are
# servers
if options.domain_name is None and options.servers is not None:
if len(options.servers) > 0:
options.domain_name = options.servers[0][
options.servers[0].find(".") + 1:]
try:
self = options
# HostNameInstallInterface
if options.ip_addresses is not None:
for value in options.ip_addresses:
try:
CheckedIPAddress(value)
except Exception as e:
raise ValueError("invalid IP address {0}: {1}".format(
value, e))
# ServiceInstallInterface
if options.domain_name:
validate_domain_name(options.domain_name)
if options.realm_name:
# pylint: disable=deprecated-method
argspec = getargspec(validate_domain_name)
if "entity" in argspec.args:
# NUM_VERSION >= 40690:
validate_domain_name(options.realm_name, entity="realm")
# ClientInstallInterface
if options.kinit_attempts < 1:
raise ValueError("expects an integer greater than 0.")
# ClientInstallInterface.__init__
if self.servers and not self.domain_name:
raise RuntimeError(
"--server cannot be used without providing --domain")
if self.force_ntpd:
logger.warning("Option --force-ntpd has been deprecated")
if self.ntp_servers and self.no_ntp:
raise RuntimeError(
"--ntp-server cannot be used together with --no-ntp")
if self.ntp_pool and self.no_ntp:
raise RuntimeError(
"--ntp-pool cannot be used together with --no-ntp")
if self.no_nisdomain and self.nisdomain:
raise RuntimeError(
"--no-nisdomain cannot be used together with --nisdomain")
if self.ip_addresses:
if self.enable_dns_updates:
raise RuntimeError(
"--ip-address cannot be used together with"
" --enable-dns-updates")
if self.all_ip_addresses:
raise RuntimeError(
"--ip-address cannot be used together with"
"--all-ip-addresses")
# SSSDInstallInterface
self.no_sssd = False
# ClientInstall
if options.ca_cert_files is not None:
for value in options.ca_cert_files:
if not isinstance(value, list):
raise ValueError("Expected list, got {0!r}".format(value))
# this is what init() does
value = value[-1]
if not os.path.exists(value):
raise ValueError("'%s' does not exist" % value)
if not os.path.isfile(value):
raise ValueError("'%s' is not a file" % value)
if not os.path.isabs(value):
raise ValueError("'%s' is not an absolute file path" %
value)
try:
x509.load_certificate_from_file(value)
except Exception:
raise ValueError("'%s' is not a valid certificate file" %
value)
# self.prompt_password = self.interactive
self.no_ac = False
# ClientInstall.__init__
if self.firefox_dir and not self.configure_firefox:
raise RuntimeError(
"--firefox-dir cannot be used without --configure-firefox "
"option")
except (RuntimeError, ValueError) as e:
module.fail_json(msg=str(e))
# ipaclient.install.client.init
# root_logger
options.debug = False
if options.domain_name:
options.domain = normalize_hostname(installer.domain_name)
else:
options.domain = None
options.server = options.servers
options.realm = options.realm_name
# installer.primary = installer.fixed_primary
# if installer.principal:
# installer.password = installer.admin_password
# else:
# installer.password = installer.host_password
installer.hostname = installer.host_name
options.conf_ntp = not options.no_ntp
# installer.trust_sshfp = installer.ssh_trust_dns
# installer.conf_ssh = not installer.no_ssh
# installer.conf_sshd = not installer.no_sshd
# installer.conf_sudo = not installer.no_sudo
# installer.create_sshfp = not installer.no_dns_sshfp
if installer.ca_cert_files:
installer.ca_cert_file = installer.ca_cert_files[-1]
else:
installer.ca_cert_file = None
# installer.location = installer.automount_location
installer.dns_updates = installer.enable_dns_updates
# installer.krb5_offline_passwords = \
# not installer.no_krb5_offline_passwords
installer.sssd = not installer.no_sssd
selinux_works = False
try:
# client
# global variables
hostname = None
hostname_source = None
nosssd_files = {}
dnsok = False
cli_domain = None
cli_server = None
# subject_base = None
cli_realm = None
cli_kdc = None
client_domain = None
cli_basedn = None
# end of global variables
# client.install_check
logger.info("This program will set up FreeIPA client.")
logger.info("Version %s", version.VERSION)
logger.info("")
cli_domain_source = 'Unknown source'
cli_server_source = 'Unknown source'
# fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
if not os.getegid() == 0:
raise ScriptError(
"You must be root to run ipa-client-install.",
rval=CLIENT_INSTALL_ERROR)
selinux_works = tasks.check_selinux_status()
# if is_ipa_client_installed(fstore, on_master=options.on_master):
# logger.error("IPA client is already configured on this system.")
# logger.info(
# "If you want to reinstall the IPA client, uninstall it first "
# "using 'ipa-client-install --uninstall'.")
# raise ScriptError(
# "IPA client is already configured on this system.",
# rval=CLIENT_ALREADY_CONFIGURED)
if check_ldap_conf is not None:
check_ldap_conf()
if options.conf_ntp:
try:
timeconf.check_timedate_services()
except timeconf.NTPConflictingService as e:
logger.info(
"WARNING: conflicting time&date synchronization service "
"'%s' will be disabled in favor of chronyd",
e.conflicting_service)
logger.info("")
except timeconf.NTPConfigurationError:
pass
# password, principal and keytab are checked in tasks/install.yml
# if options.unattended and (
# options.password is None and
# options.principal is None and
# options.keytab is None and
# options.prompt_password is False and
# not options.on_master
# ):
# raise ScriptError(
# "One of password / principal / keytab is required.",
# rval=CLIENT_INSTALL_ERROR)
if options.hostname:
hostname = options.hostname
hostname_source = 'Provided as option'
else:
hostname = socket.getfqdn()
hostname_source = "Machine's FQDN"
if hostname != hostname.lower():
raise ScriptError(
"Invalid hostname '{0}', must be lower-case.".format(hostname),
rval=CLIENT_INSTALL_ERROR
)
if hostname in ('localhost', 'localhost.localdomain'):
raise ScriptError(
"Invalid hostname, '{0}' must not be used.".format(hostname),
rval=CLIENT_INSTALL_ERROR)
if hasattr(constants, "MAXHOSTNAMELEN"):
try:
validate_hostname(hostname, maxlen=constants.MAXHOSTNAMELEN)
except ValueError as e:
raise ScriptError(
'invalid hostname: {0}'.format(e),
rval=CLIENT_INSTALL_ERROR)
if hasattr(tasks, "is_nosssd_supported"):
# --no-sssd is not supported any more for rhel-based distros
if not tasks.is_nosssd_supported() and not options.sssd:
raise ScriptError(
"Option '--no-sssd' is incompatible with the 'authselect' "
"tool provided by this distribution for configuring "
"system authentication resources",
rval=CLIENT_INSTALL_ERROR)
# --noac is not supported any more for rhel-based distros
if not tasks.is_nosssd_supported() and options.no_ac:
raise ScriptError(
"Option '--noac' is incompatible with the 'authselect' "
"tool provided by this distribution for configuring "
"system authentication resources",
rval=CLIENT_INSTALL_ERROR)
# when installing with '--no-sssd' option, check whether nss-ldap is
# installed
if not options.sssd:
if not os.path.exists(paths.PAM_KRB5_SO):
raise ScriptError(
"The pam_krb5 package must be installed",
rval=CLIENT_INSTALL_ERROR)
(nssldap_installed, nosssd_files) = nssldap_exists()
if not nssldap_installed:
raise ScriptError(
"One of these packages must be installed: nss_ldap or "
"nss-pam-ldapd",
rval=CLIENT_INSTALL_ERROR)
# principal and keytab are checked in tasks/install.yml
# if options.keytab and options.principal:
# raise ScriptError(
# "Options 'principal' and 'keytab' cannot be used together.",
# rval=CLIENT_INSTALL_ERROR)
# keytab and force_join are checked in tasks/install.yml
# if options.keytab and options.force_join:
# logger.warning("Option 'force-join' has no additional effect "
# "when used with together with option 'keytab'.")
# Added with freeipa-4.7.1 >>>
# Remove invalid keytab file
try:
gssapi.Credentials(
store={'keytab': paths.KRB5_KEYTAB},
usage='accept',
)
except gssapi.exceptions.GSSError:
logger.debug("Deleting invalid keytab: '%s'.", paths.KRB5_KEYTAB)
remove_file(paths.KRB5_KEYTAB)
# Added with freeipa-4.7.1 <<<
# Check if old certificate exist and show warning
if (
not options.ca_cert_file and
get_cert_path(options.ca_cert_file) == paths.IPA_CA_CRT
):
logger.warning("Using existing certificate '%s'.",
paths.IPA_CA_CRT)
if not check_ip_addresses(options):
raise ScriptError(
"Failed to check ip addresses, check installation log",
rval=CLIENT_INSTALL_ERROR)
# Create the discovery instance
# pylint: disable=invalid-name
ds = ipadiscovery.IPADiscovery()
ret = ds.search(
domain=options.domain,
servers=options.server,
realm=options.realm_name,
hostname=hostname,
ca_cert_path=get_cert_path(options.ca_cert_file)
)
if options.server and ret != 0:
# There is no point to continue with installation as server list
# was passed as a fixed list of server and thus we cannot discover
# any better result
logger.error(
"Failed to verify that %s is an IPA Server.",
', '.join(options.server))
logger.error(
"This may mean that the remote server is not up "
"or is not reachable due to network or firewall settings.")
print_port_conf_info()
raise ScriptError("Failed to verify that %s is an IPA Server." %
', '.join(options.server),
rval=CLIENT_INSTALL_ERROR)
if ret == ipadiscovery.BAD_HOST_CONFIG:
logger.error("Can't get the fully qualified name of this host")
logger.info("Check that the client is properly configured")
raise ScriptError(
"Can't get the fully qualified name of this host",
rval=CLIENT_INSTALL_ERROR)
if ret == ipadiscovery.NOT_FQDN:
raise ScriptError(
"{0} is not a fully-qualified hostname".format(hostname),
rval=CLIENT_INSTALL_ERROR)
if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \
or not ds.domain:
if ret == ipadiscovery.NO_LDAP_SERVER:
if ds.server:
logger.debug("%s is not an LDAP server", ds.server)
else:
logger.debug("No LDAP server found")
elif ret == ipadiscovery.NOT_IPA_SERVER:
if ds.server:
logger.debug("%s is not an IPA server", ds.server)
else:
logger.debug("No IPA server found")
else:
logger.debug("Domain not found")
if options.domain:
cli_domain = options.domain
cli_domain_source = 'Provided as option'
elif options.unattended:
raise ScriptError(
"Unable to discover domain, not provided on command line",
rval=CLIENT_INSTALL_ERROR)
else:
raise ScriptError("No interactive installation")
# logger.info(
# "DNS discovery failed to determine your DNS domain")
# cli_domain = user_input(
# "Provide the domain name of your IPA server "
# "(ex: example.com)",
# allow_empty=False)
# cli_domain_source = 'Provided interactively'
# logger.debug(
# "will use interactively provided domain: %s", cli_domain)
ret = ds.search(
domain=cli_domain,
servers=options.server,
hostname=hostname,
ca_cert_path=get_cert_path(options.ca_cert_file))
if not cli_domain:
if ds.domain:
cli_domain = ds.domain
cli_domain_source = ds.domain_source
logger.debug("will use discovered domain: %s", cli_domain)
client_domain = hostname[hostname.find(".") + 1:]
if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \
or not ds.server:
logger.debug("IPA Server not found")
if options.server:
cli_server = options.server
cli_server_source = 'Provided as option'
elif options.unattended:
raise ScriptError(
"Unable to find IPA Server to join",
rval=CLIENT_INSTALL_ERROR)
else:
raise ScriptError("No interactive installation")
# logger.debug("DNS discovery failed to find the IPA Server")
# cli_server = [
# user_input(
# "Provide your IPA server name (ex: ipa.example.com)",
# allow_empty=False)
# ]
# cli_server_source = 'Provided interactively'
# logger.debug(
# "will use interactively provided server: %s", cli_server[0])
ret = ds.search(
domain=cli_domain,
servers=cli_server,
hostname=hostname,
ca_cert_path=get_cert_path(options.ca_cert_file))
else:
# Only set dnsok to True if we were not passed in one or more
# servers and if DNS discovery actually worked.
if not options.server:
(server, domain) = ds.check_domain(
ds.domain, set(), "Validating DNS Discovery")
if server and domain:
logger.debug("DNS validated, enabling discovery")
dnsok = True
else:
logger.debug("DNS discovery failed, disabling discovery")
else:
logger.debug(
"Using servers from command line, disabling DNS discovery")
if not cli_server:
if options.server:
cli_server = ds.servers
cli_server_source = 'Provided as option'
logger.debug(
"will use provided server: %s", ', '.join(options.server))
elif ds.server:
cli_server = ds.servers
cli_server_source = ds.server_source
logger.debug("will use discovered server: %s", cli_server[0])
if ret == ipadiscovery.NOT_IPA_SERVER:
logger.error("%s is not an IPA v2 Server.", cli_server[0])
print_port_conf_info()
logger.debug("(%s: %s)", cli_server[0], cli_server_source)
raise ScriptError("%s is not an IPA v2 Server." % cli_server[0],
rval=CLIENT_INSTALL_ERROR)
if ret == ipadiscovery.NO_ACCESS_TO_LDAP:
logger.warning("Anonymous access to the LDAP server is disabled.")
logger.info("Proceeding without strict verification.")
logger.info(
"Note: This is not an error if anonymous access "
"has been explicitly restricted.")
ret = 0
if ret == ipadiscovery.NO_TLS_LDAP:
logger.warning(
"The LDAP server requires TLS is but we do not have the CA.")
logger.info("Proceeding without strict verification.")
ret = 0
if ret != 0:
logger.error(
"Failed to verify that %s is an IPA Server.",
cli_server[0])
logger.error(
"This may mean that the remote server is not up "
"or is not reachable due to network or firewall settings.")
print_port_conf_info()
logger.debug("(%s: %s)", cli_server[0], cli_server_source)
raise ScriptError("Failed to verify that %s is an IPA Server." %
cli_server[0],
rval=CLIENT_INSTALL_ERROR)
cli_kdc = ds.kdc
if dnsok and not cli_kdc:
logger.error(
"DNS domain '%s' is not configured for automatic "
"KDC address lookup.", ds.realm.lower())
logger.debug("(%s: %s)", ds.realm, ds.realm_source)
logger.error("KDC address will be set to fixed value.")
if dnsok:
logger.info("Discovery was successful!")
elif not options.unattended:
raise ScriptError("No interactive installation")
# if not options.server:
# logger.warning(
# "The failure to use DNS to find your IPA "
# "server indicates that your resolv.conf file is not properly "
# "configured.")
# logger.info(
# "Autodiscovery of servers for failover cannot work "
# "with this configuration.")
# logger.info(
# "If you proceed with the installation, services "
# "will be configured to always access the discovered server for "
# "all operations and will not fail over to other servers in case "
# "of failure.")
# if not user_input(
# "Proceed with fixed values and no DNS discovery?", False):
# raise ScriptError(rval=CLIENT_INSTALL_ERROR)
# Do not ask for time source
# if options.conf_ntp:
# if not options.on_master and not options.unattended and not (
# options.ntp_servers or options.ntp_pool):
# options.ntp_servers, options.ntp_pool = \
# timeconf.get_time_source()
cli_realm = ds.realm
cli_realm_source = ds.realm_source
logger.debug("will use discovered realm: %s", cli_realm)
if options.realm_name and options.realm_name != cli_realm:
logger.error(
"The provided realm name [%s] does not match discovered "
"one [%s]",
options.realm_name, cli_realm)
logger.debug("(%s: %s)", cli_realm, cli_realm_source)
raise ScriptError(
"The provided realm name [%s] does not match discovered "
"one [%s]" % (options.realm_name, cli_realm),
rval=CLIENT_INSTALL_ERROR)
cli_basedn = ds.basedn
cli_basedn_source = ds.basedn_source
logger.debug("will use discovered basedn: %s", cli_basedn)
# subject_base = DN(('O', cli_realm))
logger.info("Client hostname: %s", hostname)
logger.debug("Hostname source: %s", hostname_source)
logger.info("Realm: %s", cli_realm)
logger.debug("Realm source: %s", cli_realm_source)
logger.info("DNS Domain: %s", cli_domain)
logger.debug("DNS Domain source: %s", cli_domain_source)
logger.info("IPA Server: %s", ', '.join(cli_server))
logger.debug("IPA Server source: %s", cli_server_source)
logger.info("BaseDN: %s", cli_basedn)
logger.debug("BaseDN source: %s", cli_basedn_source)
if not options.on_master:
if options.ntp_servers:
for server in options.ntp_servers:
logger.info("NTP server: %s", server)
if options.ntp_pool:
logger.info("NTP pool: %s", options.ntp_pool)
# ipa-join would fail with IP address instead of a FQDN
for srv in cli_server:
try:
socket.inet_pton(socket.AF_INET, srv)
is_ipaddr = True
except socket.error:
try:
socket.inet_pton(socket.AF_INET6, srv)
is_ipaddr = True
except socket.error:
is_ipaddr = False
if is_ipaddr:
logger.warning(
"It seems that you are using an IP address "
"instead of FQDN as an argument to --server. The "
"installation may fail.")
break
# logger.info()
# if not options.unattended and not user_input(
# "Continue to configure the system with these values?", False):
# raise ScriptError(rval=CLIENT_INSTALL_ERROR)
except ScriptError as e:
module.fail_json(msg=str(e))
#########################################################################
# client._install
# May not happen in here at this time
# if not options.on_master:
# # Try removing old principals from the keytab
# purge_host_keytab(cli_realm)
# Check if ipa client is already configured
if is_client_configured():
client_already_configured = True
# Check that realm and domain match
current_config = get_ipa_conf()
if cli_domain != current_config.get('domain'):
module.fail_json(msg="IPA client already installed "
"with a conflicting domain")
if cli_realm != current_config.get('realm'):
module.fail_json(msg="IPA client already installed "
"with a conflicting realm")
else:
client_already_configured = False
# Done
module.exit_json(changed=False,
servers=cli_server,
domain=cli_domain,
realm=cli_realm,
kdc=cli_kdc,
basedn=str(cli_basedn),
hostname=hostname,
client_domain=client_domain,
dnsok=dnsok,
sssd=options.sssd,
ntp_servers=options.ntp_servers,
ntp_pool=options.ntp_pool,
client_already_configured=client_already_configured,
ipa_python_version=IPA_PYTHON_VERSION,
nosssd_files=nosssd_files,
selinux_works=selinux_works)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/library/ipaclient_test_keytab.py 0000664 0000000 0000000 00000017241 14600563364 0027071 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaclient_test_keytab
short_description:
Test if the krb5.keytab on the machine is valid and can be used.
description:
Test if the krb5.keytab on the machine is valid and can be used.
A temporary krb5.conf file will be generated to not fail on an invalid one.
options:
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: yes
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: yes
kdc:
description: The name or address of the host running the KDC
type: str
required: yes
kinit_attempts:
description: Repeat the request for host Kerberos ticket X times
type: int
default: 5
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
# Test IPA with local keytab
- name: Test IPA in force mode with maximum 5 kinit attempts
ipaclient_test_keytab:
servers: ["server1.example.com","server2.example.com"]
domain: example.com
realm: EXAMPLE.COM
kdc: server1.example.com
hostname: client1.example.com
kinit_attempts: 5
# Test IPA with ipadiscovery return values
- name: Join IPA
ipaclient_test_keytab:
servers: "{{ ipadiscovery.servers }}"
domain: "{{ ipadiscovery.domain }}"
realm: "{{ ipadiscovery.realm }}"
kdc: "{{ ipadiscovery.kdc }}"
hostname: "{{ ipadiscovery.hostname }}"
'''
RETURN = '''
krb5_keytab_ok:
description: The flag describes if krb5.keytab on the host is usable.
returned: always
type: bool
ca_crt_exists:
description: The flag describes if ca.crt exists.
returned: always
type: str
krb5_conf_ok:
description: The flag describes if krb5.conf on the host is usable.
returned: always
type: bool
ping_test_ok:
description: The flag describes if ipa ping test succeded.
returned: always
type: bool
'''
import os
import tempfile
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, check_imports,
SECURE_PATH, paths, kinit_keytab, run, GSSError, configure_krb5_conf
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list', elements='str'),
domain=dict(required=True, type='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=True, type='str'),
kdc=dict(required=True, type='str'),
kinit_attempts=dict(required=False, type='int', default=5),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
servers = module.params.get('servers')
domain = module.params.get('domain')
realm = module.params.get('realm')
hostname = module.params.get('hostname')
kdc = module.params.get('kdc')
kinit_attempts = module.params.get('kinit_attempts')
client_domain = hostname[hostname.find(".") + 1:]
host_principal = 'host/%s@%s' % (hostname, realm)
sssd = True
# Remove IPA_DNS_CCACHE remain if it exists
try:
os.remove(paths.IPA_DNS_CCACHE)
except OSError:
pass
krb5_keytab_ok = False
krb5_conf_ok = False
ping_test_ok = False
ca_crt_exists = os.path.exists(paths.IPA_CA_CRT)
env = {'PATH': SECURE_PATH, 'KRB5CCNAME': paths.IPA_DNS_CCACHE}
# First try: Validate with temporary test krb5.conf that forces
# 1) no DNS lookups and
# 2) to load /etc/krb5.conf:
#
# [libdefaults]
# dns_lookup_realm = false
# dns_lookup_kdc = false
# include /etc/krb5.conf
#
try:
(krb_fd, krb_name) = tempfile.mkstemp()
os.close(krb_fd)
content = "\n".join([
"[libdefaults]",
"dns_lookup_realm = false",
"dns_lookup_kdc = false",
"include /etc/krb5.conf"
])
with open(krb_name, "w") as outf:
outf.write(content)
kinit_keytab(host_principal, paths.KRB5_KEYTAB,
paths.IPA_DNS_CCACHE,
config=krb_name,
attempts=kinit_attempts)
krb5_keytab_ok = True
krb5_conf_ok = True
# Test IPA
try:
result = run(["/usr/bin/ipa", "ping"], raiseonerr=False, env=env)
if result.returncode == 0:
ping_test_ok = True
except OSError:
pass
except GSSError:
pass
finally:
try:
os.remove(krb_name)
except OSError:
module.fail_json(msg="Could not remove %s" % krb_name)
# Second try: Validate krb5 keytab with temporary krb5
# configuration
if not krb5_conf_ok:
try:
(krb_fd, krb_name) = tempfile.mkstemp()
os.close(krb_fd)
configure_krb5_conf(
cli_realm=realm,
cli_domain=domain,
cli_server=servers,
cli_kdc=kdc,
dnsok=False,
filename=krb_name,
client_domain=client_domain,
client_hostname=hostname,
configure_sssd=sssd,
force=False)
try:
kinit_keytab(host_principal, paths.KRB5_KEYTAB,
paths.IPA_DNS_CCACHE,
config=krb_name,
attempts=kinit_attempts)
krb5_keytab_ok = True
# Test IPA
env['KRB5_CONFIG'] = krb_name
try:
result = run(["/usr/bin/ipa", "ping"], raiseonerr=False,
env=env)
if result.returncode == 0:
ping_test_ok = True
except OSError:
pass
except GSSError:
pass
finally:
try:
os.remove(krb_name)
except OSError:
module.fail_json(msg="Could not remove %s" % krb_name)
if os.path.exists(krb_name + ".ipabkp"):
try:
os.remove(krb_name + ".ipabkp")
except OSError:
module.fail_json(
msg="Could not remove %s.ipabkp" % krb_name)
module.exit_json(changed=False,
krb5_keytab_ok=krb5_keytab_ok,
krb5_conf_ok=krb5_conf_ok,
ca_crt_exists=ca_crt_exists,
ping_test_ok=ping_test_ok)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaclient/meta/ 0000775 0000000 0000000 00000000000 14600563364 0021426 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaclient/meta/main.yml 0000664 0000000 0000000 00000000556 14600563364 0023103 0 ustar 00root root 0000000 0000000 ---
dependencies: []
galaxy_info:
author: Florence Blanc-Renaud, Thomas Woerner
description: A role to join a machine to an IPA domain
company: Red Hat, Inc
license: GPLv3
min_ansible_version: "2.13"
platforms:
- name: Fedora
versions:
- all
- name: EL
versions:
- "7"
- "8"
galaxy_tags:
- identity
- ipa
- freeipa
ansible-freeipa-master/roles/ipaclient/module_utils/ 0000775 0000000 0000000 00000000000 14600563364 0023205 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaclient/module_utils/ansible_ipa_client.py 0000664 0000000 0000000 00000034064 14600563364 0027372 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__all__ = ["gssapi", "version", "ipadiscovery", "api", "errors", "x509",
"constants", "sysrestore", "certmonger", "certstore",
"delete_persistent_client_session_data", "ScriptError",
"CheckedIPAddress", "validate_domain_name", "normalize_hostname",
"validate_hostname", "services", "tasks", "CalledProcessError",
"write_tmp_file", "ipa_generate_password", "DN", "kinit_keytab",
"kinit_password", "GSSError", "CLIENT_INSTALL_ERROR",
"is_ipa_client_installed", "CLIENT_ALREADY_CONFIGURED",
"nssldap_exists", "remove_file", "check_ip_addresses",
"print_port_conf_info", "configure_ipa_conf", "purge_host_keytab",
"configure_sssd_conf", "realm_to_suffix", "run", "timeconf",
"serialization", "configure_krb5_conf", "get_ca_certs",
"SECURE_PATH", "get_server_connection_interface",
"disable_ra", "client_dns",
"configure_certmonger", "update_ssh_keys",
"configure_openldap_conf", "hardcode_ldap_server",
"get_certs_from_ldap", "save_state", "create_ipa_nssdb",
"configure_nisdomain", "configure_ldap_conf",
"configure_nslcd_conf", "configure_ssh_config",
"configure_sshd_config", "configure_automount",
"configure_firefox", "sync_time", "check_ldap_conf",
"sssd_enable_ifp", "configure_selinux_for_client",
"getargspec", "paths", "options",
"IPA_PYTHON_VERSION", "NUM_VERSION", "certdb", "get_ca_cert",
"ipalib", "logger", "ipautil", "installer"]
import sys
# Import getargspec from inspect or provide own getargspec for
# Python 2 compatibility with Python 3.11+.
try:
from inspect import getargspec
except ImportError:
from collections import namedtuple
from inspect import getfullargspec
# The code is copied from Python 3.10 inspect.py
# Authors: Ka-Ping Yee
# Yury Selivanov
ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults')
def getargspec(func):
args, varargs, varkw, defaults, kwonlyargs, _kwonlydefaults, \
ann = getfullargspec(func)
if kwonlyargs or ann:
raise ValueError(
"Function has keyword-only parameters or annotations"
", use inspect.signature() API which can support them")
return ArgSpec(args, varargs, varkw, defaults)
try:
from ipapython.version import NUM_VERSION, VERSION
if NUM_VERSION < 30201:
# See ipapython/version.py
IPA_MAJOR, IPA_MINOR, IPA_RELEASE = [int(x) for x in
VERSION.split(".", 2)]
IPA_PYTHON_VERSION = IPA_MAJOR * 10000 + IPA_MINOR * 100 + IPA_RELEASE
else:
IPA_PYTHON_VERSION = NUM_VERSION
# pylint: disable=invalid-name,useless-object-inheritance
class installer_obj(object):
def __init__(self):
pass
# pylint: disable=attribute-defined-outside-init
def set_logger(self, _logger):
self.logger = _logger
# def __getattribute__(self, attr):
# value = super(installer_obj, self).__getattribute__(attr)
# if not attr.startswith("--") and not attr.endswith("--"):
# logger.debug(
# " <-- Accessing installer.%s (%s)" % (attr, repr(value)))
# return value
# def __getattr__(self, attr):
# # logger.info(" --> ADDING missing installer.%s" % attr)
# self.logger.warn(" --> ADDING missing installer.%s" % attr)
# setattr(self, attr, None)
# return getattr(self, attr)
# def __setattr__(self, attr, value):
# logger.debug(" --> Setting installer.%s to %s" %
# (attr, repr(value)))
# return super(installer_obj, self).__setattr__(attr, value)
def knobs(self):
for name in self.__dict__:
yield self, name
# Initialize installer settings
installer = installer_obj()
# Create options
options = installer
# pylint: disable=attribute-defined-outside-init
options.interactive = False
options.unattended = not options.interactive
if NUM_VERSION >= 40400:
# IPA version >= 4.4
# import sys
import gssapi
import logging
from ipapython import version
try:
from ipaclient.install import ipadiscovery
except ImportError:
from ipaclient import ipadiscovery
import ipalib
from ipalib import api, errors, x509
from ipalib import constants
try:
from ipalib import sysrestore
except ImportError:
try:
from ipalib.install import sysrestore
except ImportError:
from ipapython import sysrestore
try:
from ipalib.install import certmonger
except ImportError:
from ipapython import certmonger
try:
from ipalib.install import certstore
except ImportError:
from ipalib import certstore
from ipalib.rpc import delete_persistent_client_session_data
from ipapython import certdb, ipautil
from ipapython.admintool import ScriptError
from ipapython.ipautil import CheckedIPAddress
from ipalib.util import validate_domain_name, normalize_hostname, \
validate_hostname
from ipaplatform import services
from ipaplatform.paths import paths
from ipaplatform.tasks import tasks
try:
from cryptography.hazmat.primitives import serialization
except ImportError:
serialization = None
from ipapython.ipautil import CalledProcessError, write_tmp_file, \
ipa_generate_password
from ipapython.dn import DN
try:
from ipalib.install.kinit import kinit_keytab, kinit_password
except ImportError:
from ipapython.ipautil import kinit_keytab, kinit_password
from ipapython.ipa_log_manager import standard_logging_setup
from gssapi.exceptions import GSSError
try:
from ipaclient.install.client import configure_krb5_conf, \
get_ca_certs, SECURE_PATH, get_server_connection_interface, \
disable_ra, client_dns, \
configure_certmonger, update_ssh_keys, \
configure_openldap_conf, \
hardcode_ldap_server, get_certs_from_ldap, save_state, \
create_ipa_nssdb, configure_ssh_config, \
configure_sshd_config, \
configure_automount, configure_firefox, configure_nisdomain, \
CLIENT_INSTALL_ERROR, is_ipa_client_installed, \
CLIENT_ALREADY_CONFIGURED, nssldap_exists, remove_file, \
check_ip_addresses, print_port_conf_info, configure_ipa_conf, \
purge_host_keytab, configure_sssd_conf, configure_ldap_conf, \
configure_nslcd_conf
get_ca_cert = None
except ImportError:
# Create temporary copy of ipa-client-install script (as
# ipa_client_install.py) to be able to import the script easily
# and also to remove the global finally clause in which the
# generated ccache file gets removed. The ccache file will be
# needed in the next step.
# This is done in a temporary directory that gets removed right
# after ipa_client_install has been imported.
import shutil
import tempfile
temp_dir = tempfile.mkdtemp(dir="/tmp")
sys.path.append(temp_dir)
temp_file = "%s/ipa_client_install.py" % temp_dir
with open("/usr/sbin/ipa-client-install", "r") as f_in:
with open(temp_file, "w") as f_out:
for line in f_in:
if line.startswith("finally:"):
break
f_out.write(line)
import ipa_client_install
shutil.rmtree(temp_dir, ignore_errors=True)
sys.path.remove(temp_dir)
# pylint: disable=deprecated-method
argspec = getargspec(
ipa_client_install.configure_krb5_conf)
if argspec.keywords is None:
def configure_krb5_conf(
cli_realm, cli_domain, cli_server, cli_kdc, dnsok,
filename, client_domain, client_hostname, force=False,
configure_sssd=True):
# pylint: disable=global-variable-not-assigned
global options
options.force = force
options.sssd = configure_sssd
return ipa_client_install.configure_krb5_conf(
cli_realm, cli_domain, cli_server, cli_kdc, dnsok,
options, filename, client_domain, client_hostname)
else:
configure_krb5_conf = ipa_client_install.configure_krb5_conf
if NUM_VERSION < 40100:
get_ca_cert = ipa_client_install.get_ca_cert
get_ca_certs = None
else:
get_ca_cert = None
get_ca_certs = ipa_client_install.get_ca_certs
SECURE_PATH = ("/bin:/sbin:/usr/kerberos/bin:/usr/kerberos/sbin:"
"/usr/bin:/usr/sbin")
get_server_connection_interface = \
ipa_client_install.get_server_connection_interface
disable_ra = ipa_client_install.disable_ra
client_dns = ipa_client_install.client_dns
configure_certmonger = ipa_client_install.configure_certmonger
update_ssh_keys = ipa_client_install.update_ssh_keys
configure_openldap_conf = \
ipa_client_install.configure_openldap_conf
hardcode_ldap_server = ipa_client_install.hardcode_ldap_server
get_certs_from_ldap = ipa_client_install.get_certs_from_ldap
save_state = ipa_client_install.save_state
create_ipa_nssdb = certdb.create_ipa_nssdb
argspec = \
getargspec(ipa_client_install.configure_nisdomain)
if len(argspec.args) == 3:
configure_nisdomain = ipa_client_install.configure_nisdomain
else:
def configure_nisdomain(_options, domain, _statestore=None):
return ipa_client_install.configure_nisdomain(_options,
domain)
configure_ldap_conf = ipa_client_install.configure_ldap_conf
configure_nslcd_conf = ipa_client_install.configure_nslcd_conf
configure_ssh_config = ipa_client_install.configure_ssh_config
configure_sshd_config = ipa_client_install.configure_sshd_config
configure_automount = ipa_client_install.configure_automount
configure_firefox = ipa_client_install.configure_firefox
from ipapython.ipautil import realm_to_suffix, run
try:
from ipaclient.install import timeconf
time_service = "chronyd"
except ImportError:
try:
from ipaclient.install import ntpconf as timeconf
except ImportError:
from ipaclient import ntpconf as timeconf
time_service = "ntpd"
try:
from ipaclient.install.client import sync_time
except ImportError:
sync_time = None
try:
from ipaclient.install.client import check_ldap_conf
except ImportError:
check_ldap_conf = None
try:
from ipaclient.install.client import sssd_enable_ifp
except ImportError:
sssd_enable_ifp = None
try:
from ipaclient.install.client import configure_selinux_for_client
except ImportError:
configure_selinux_for_client = None
logger = logging.getLogger("ipa-client-install")
root_logger = logger
else:
# IPA version < 4.4
raise RuntimeError("freeipa version '%s' is too old" % VERSION)
except ImportError as _err:
ANSIBLE_IPA_CLIENT_MODULE_IMPORT_ERROR = str(_err)
for attr in __all__:
setattr(sys.modules[__name__], attr, None)
else:
ANSIBLE_IPA_CLIENT_MODULE_IMPORT_ERROR = None
def setup_logging():
standard_logging_setup(
paths.IPACLIENT_INSTALL_LOG, verbose=False, debug=False,
filemode='a', console_format='%(message)s')
def ansible_module_get_parsed_ip_addresses(ansible_module,
param='ip_addresses'):
ip_addresses = ansible_module.params.get(param)
if ip_addresses is None:
return None
ip_addrs = []
for ip in ip_addresses:
try:
ip_parsed = ipautil.CheckedIPAddress(ip)
except Exception as e:
ansible_module.fail_json(msg="Invalid IP Address %s: %s" % (ip, e))
ip_addrs.append(ip_parsed)
return ip_addrs
def check_imports(module):
if ANSIBLE_IPA_CLIENT_MODULE_IMPORT_ERROR is not None:
module.fail_json(msg=ANSIBLE_IPA_CLIENT_MODULE_IMPORT_ERROR)
ansible-freeipa-master/roles/ipaclient/tasks/ 0000775 0000000 0000000 00000000000 14600563364 0021625 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaclient/tasks/install.yml 0000664 0000000 0000000 00000047256 14600563364 0024034 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipaclient
- name: Install - Ensure that IPA client packages are installed
ansible.builtin.package:
name: "{{ ipaclient_packages }}"
state: present
when: ipaclient_install_packages | bool
- name: Install - Set ipaclient_servers
ansible.builtin.set_fact:
ipaclient_servers: "{{ groups['ipaservers'] | list }}"
when: groups.ipaservers is defined and ipaclient_servers is not defined
- name: Install - Set ipaclient_servers from cluster inventory
ansible.builtin.set_fact:
ipaclient_servers: "{{ groups['ipaserver'] | list }}"
when: ipaclient_no_dns_lookup | bool and groups.ipaserver is defined and
ipaclient_servers is not defined
- name: Install - Check that either password or keytab is set
ansible.builtin.fail:
msg: "ipaadmin_password and ipaadmin_keytab cannot be used together"
when: ipaadmin_keytab is defined and ipaadmin_password is defined
- name: Install - Set default principal if no keytab is given
ansible.builtin.set_fact:
ipaadmin_principal: admin
when: ipaadmin_principal is undefined and ipaclient_keytab is undefined
- name: Install - DNS resolver configuration
when: ipaclient_configure_dns_resolver | bool
and not ipaclient_on_master | bool
block:
- name: Install - Fail on missing ipaclient_domain and ipaserver_domain
ansible.builtin.fail:
msg: "ipaclient_domain or ipaserver_domain is required for ipaclient_configure_dns_resolver"
when: ipaserver_domain is not defined and ipaclient_domain is not defined
- name: Install - Fail on missing ipaclient_servers
ansible.builtin.fail:
msg: "ipaclient_dns_servers is required for ipaclient_configure_dns_resolver"
when: ipaclient_dns_servers is not defined
- name: Install - Configure DNS resolver
ipaclient_configure_dns_resolver:
nameservers: "{{ ipaclient_dns_servers }}"
searchdomains: "{{ ipaserver_domain | default(ipaclient_domain) }}"
state: present
- name: Install - IPA client test
ipaclient_test:
### basic ###
domain: "{{ ipaserver_domain | default(ipaclient_domain) | default(omit) }}"
servers: "{{ ipaclient_servers | default(omit) }}"
realm: "{{ ipaserver_realm | default(ipaclient_realm) | default(omit) }}"
hostname: "{{ ipaclient_hostname | default(ansible_facts['fqdn']) }}"
ntp_servers: "{{ ipaclient_ntp_servers | default(omit) }}"
ntp_pool: "{{ ipaclient_ntp_pool | default(omit) }}"
no_ntp: "{{ ipaclient_no_ntp }}"
force_ntpd: "{{ ipaclient_force_ntpd }}"
nisdomain: "{{ ipaclient_nisdomain | default(omit) }}"
no_nisdomain: "{{ ipaclient_no_nisdomain }}"
kinit_attempts: "{{ ipaclient_kinit_attempts }}"
ca_cert_files: "{{ ipaclient_ca_cert_file | default(omit) }}"
configure_firefox: "{{ ipaclient_configure_firefox }}"
firefox_dir: "{{ ipaclient_firefox_dir | default(omit) }}"
ip_addresses: "{{ ipaclient_ip_addresses | default(omit) }}"
all_ip_addresses: "{{ ipaclient_all_ip_addresses }}"
on_master: "{{ ipaclient_on_master }}"
### sssd ###
enable_dns_updates: "{{ ipassd_enable_dns_updates
| default(ipasssd_enable_dns_updates) }}"
register: result_ipaclient_test
- name: Install - Client deployment
when: not ansible_check_mode and
not (result_ipaclient_test.client_already_configured and
not ipaclient_allow_repair | bool and not ipaclient_force_join | bool)
block:
- name: Install - Cleanup leftover ccache
ansible.builtin.file:
path: "/etc/ipa/.dns_ccache"
state: absent
- name: Install - Configure NTP
ipaclient_setup_ntp:
### basic ###
ntp_servers: "{{ result_ipaclient_test.ntp_servers | default(omit) }}"
ntp_pool: "{{ result_ipaclient_test.ntp_pool | default(omit) }}"
no_ntp: "{{ ipaclient_no_ntp }}"
# force_ntpd: "{{ ipaclient_force_ntpd }}"
on_master: "{{ ipaclient_on_master }}"
### additional ###
servers: "{{ result_ipaclient_test.servers }}"
domain: "{{ result_ipaclient_test.domain }}"
- name: Install - Make sure One-Time Password is enabled if it's already defined
ansible.builtin.set_fact:
ipaclient_use_otp: "yes"
when: ipaclient_otp is defined
- name: Install - Disable One-Time Password for on_master
ansible.builtin.set_fact:
ipaclient_use_otp: "no"
when: ipaclient_use_otp | bool and ipaclient_on_master | bool
- name: Install - Test if IPA client has working krb5.keytab
ipaclient_test_keytab:
servers: "{{ result_ipaclient_test.servers }}"
domain: "{{ result_ipaclient_test.domain }}"
realm: "{{ result_ipaclient_test.realm }}"
hostname: "{{ result_ipaclient_test.hostname }}"
kdc: "{{ result_ipaclient_test.kdc }}"
kinit_attempts: "{{ ipaclient_kinit_attempts | default(omit) }}"
register: result_ipaclient_test_keytab
- name: Install - Disable One-Time Password for client with working
krb5.keytab
ansible.builtin.set_fact:
ipaclient_use_otp: "no"
when: ipaclient_use_otp | bool and
result_ipaclient_test_keytab.krb5_keytab_ok and
not ipaclient_force_join | bool
# The following block is executed when using OTP to enroll IPA client and
# the OTP isn't predefined, ie when ipaclient_use_otp is set and
# ipaclient_otp is not set.
# It connects to ipaserver and add the host with --random option in order
# to create a OneTime Password
# If a keytab is specified in the hostent, then the hostent will be disabled
# if ipaclient_use_otp is set.
- name: Install - Obtain OTP
when: ipaclient_use_otp | bool and ipaclient_otp is not defined
block:
- name: Install - Keytab or password is required for getting otp
ansible.builtin.fail:
msg: "Keytab or password is required for getting otp"
when: ipaadmin_keytab is undefined and ipaadmin_password is undefined
- name: Install - Create temporary file for keytab
ansible.builtin.tempfile:
state: file
prefix: ipaclient_temp_
path: /root
register: keytab_temp
delegate_to: "{{ result_ipaclient_test.servers[0] }}"
when: ipaadmin_keytab is defined
- name: Install - Copy keytab to server temporary file
ansible.builtin.copy:
src: "{{ ipaadmin_keytab }}"
dest: "{{ keytab_temp.path }}"
mode: 0600
delegate_to: "{{ result_ipaclient_test.servers[0] }}"
when: ipaadmin_keytab is defined
- name: Install - Get One-Time Password for client enrollment
no_log: yes
ipaclient_get_otp:
ipaadmin_principal: "{{ ipaadmin_principal | default(omit) }}"
ipaadmin_password: "{{ ipaadmin_password | default(omit) }}"
ipaadmin_keytab: "{{ keytab_temp.path | default(omit) }}"
hostname: "{{ result_ipaclient_test.hostname }}"
register: result_ipaclient_get_otp
delegate_to: "{{ result_ipaclient_test.servers[0] }}"
- name: Install - Store the previously obtained OTP
no_log: yes
ansible.builtin.set_fact:
ipaadmin_orig_password: "{{ ipaadmin_password | default(omit) }}"
ipaadmin_password: "{{ result_ipaclient_get_otp.host.randompassword
if result_ipaclient_get_otp.host is defined }}"
rescue:
- name: Install - Report error for OTP generation
ansible.builtin.debug:
msg: "{{ result_ipaclient_get_otp.msg }}"
when: result_ipaclient_get_otp is failed
failed_when: yes
always:
- name: Install - Remove keytab temporary file
ansible.builtin.file:
path: "{{ keytab_temp.path }}"
state: absent
delegate_to: "{{ result_ipaclient_test.servers[0] }}"
when: keytab_temp.path is defined
- name: Store predefined OTP in admin_password
no_log: yes
ansible.builtin.set_fact:
ipaadmin_orig_password: "{{ ipaadmin_password | default(omit) }}"
ipaadmin_password: "{{ ipaclient_otp }}"
when: ipaclient_otp is defined
- name: Install - Check keytab, principal and keytab
when: not ipaclient_on_master | bool
block:
# This block is executed only when
# not (not ipaclient_on_master | bool and
# not result_ipaclient_join.changed and
# not ipaclient_allow_repair | bool and
# (result_ipaclient_test_keytab.krb5_keytab_ok or
# (result_ipaclient_join.already_joined is defined and
# result_ipaclient_join.already_joined)))
- name: Install - Check if principal and keytab are set
ansible.builtin.fail:
msg: "Admin principal and client keytab cannot be used together"
when: ipaadmin_principal is defined and ipaclient_keytab is defined
- name: Install - Check if one of password or keytabs are set
ansible.builtin.fail:
msg: "At least one of password or keytabs must be specified"
when: not result_ipaclient_test_keytab.krb5_keytab_ok
and ipaadmin_password is undefined
and ipaadmin_keytab is undefined
and ipaclient_keytab is undefined
- name: "Install - From host keytab, purge {{ result_ipaclient_test.realm }}"
ansible.builtin.command: >
/usr/sbin/ipa-rmkeytab
-k /etc/krb5.keytab
-r "{{ result_ipaclient_test.realm }}"
register: result_ipa_rmkeytab
# Do not fail on error codes 3 and 5:
# 3 - Unable to open keytab
# 5 - Principal name or realm not found in keytab
# 7 - Failed to set cursor, typically when errcode
# would be issued in past
failed_when: result_ipa_rmkeytab.rc != 0 and
result_ipa_rmkeytab.rc != 3 and
result_ipa_rmkeytab.rc != 5 and
result_ipa_rmkeytab.rc != 7
when: (ipaclient_use_otp | bool or ipaclient_force_join | bool) and not ipaclient_on_master | bool
- name: Install - Backup and set hostname
ipaclient_set_hostname:
hostname: "{{ result_ipaclient_test.hostname }}"
when: not ipaclient_on_master | bool
- name: Install - Create temporary krb5 configuration
ipaclient_temp_krb5:
servers: "{{ result_ipaclient_test.servers }}"
domain: "{{ result_ipaclient_test.domain }}"
realm: "{{ result_ipaclient_test.realm }}"
hostname: "{{ result_ipaclient_test.hostname }}"
kdc: "{{ result_ipaclient_test.kdc }}"
register: result_ipaclient_temp_krb5
- name: Install - Join IPA
ipaclient_join:
servers: "{{ result_ipaclient_test.servers }}"
realm: "{{ result_ipaclient_test.realm }}"
basedn: "{{ result_ipaclient_test.basedn }}"
hostname: "{{ result_ipaclient_test.hostname }}"
force_join: "{{ ipaclient_force_join | default(omit) }}"
principal: "{{ ipaadmin_principal if not ipaclient_use_otp | bool and
ipaclient_keytab is not defined else omit }}"
password: "{{ ipaadmin_password | default(omit) }}"
keytab: "{{ ipaclient_keytab | default(omit) }}"
admin_keytab: "{{ ipaadmin_keytab if ipaadmin_keytab is defined and not ipaclient_use_otp | bool else omit }}"
# ca_cert_file: "{{ ipaclient_ca_cert_file | default(omit) }}"
kinit_attempts: "{{ ipaclient_kinit_attempts | default(omit) }}"
krb_name: "{{ result_ipaclient_temp_krb5.krb_name }}"
register: result_ipaclient_join
when: not ipaclient_on_master | bool and
(not result_ipaclient_test_keytab.krb5_keytab_ok or
ipaclient_force_join)
- name: Install - Allow repair checks
when: not ipaclient_on_master | bool and
not result_ipaclient_join.changed and
not ipaclient_allow_repair | bool and
(result_ipaclient_test_keytab.krb5_keytab_ok or
(result_ipaclient_join.already_joined is defined and
result_ipaclient_join.already_joined))
block:
- name: The krb5 configuration is not correct
ansible.builtin.fail:
msg: >
The krb5 configuration is not correct, please enable allow_repair
to fix this.
when: not result_ipaclient_test_keytab.krb5_conf_ok
- name: IPA test failed
ansible.builtin.fail:
msg: "The IPA test failed, please enable allow_repair to fix this."
when: not result_ipaclient_test_keytab.ping_test_ok
- name: Fail due to missing ca.crt file
ansible.builtin.fail:
msg: >
The ca.crt file is missing, please enable allow_repair to fix this.
when: not result_ipaclient_test_keytab.ca_crt_exists
- name: Install - Configuration
when: not (not ipaclient_on_master | bool and
not result_ipaclient_join.changed and
not ipaclient_allow_repair | bool
and (result_ipaclient_test_keytab.krb5_keytab_ok
or (result_ipaclient_join.already_joined is defined
and result_ipaclient_join.already_joined)))
block:
- name: Install - Configure IPA default.conf
ipaclient_ipa_conf:
servers: "{{ result_ipaclient_test.servers }}"
domain: "{{ result_ipaclient_test.domain }}"
realm: "{{ result_ipaclient_test.realm }}"
hostname: "{{ result_ipaclient_test.hostname }}"
basedn: "{{ result_ipaclient_test.basedn }}"
when: not ipaclient_on_master | bool
- name: Install - Configure SSSD
ipaclient_setup_sssd:
servers: "{{ result_ipaclient_test.servers }}"
domain: "{{ result_ipaclient_test.domain }}"
realm: "{{ result_ipaclient_test.realm }}"
hostname: "{{ result_ipaclient_test.hostname }}"
on_master: "{{ ipaclient_on_master }}"
no_ssh: "{{ ipaclient_no_ssh }}"
no_sshd: "{{ ipaclient_no_sshd }}"
no_sudo: "{{ ipaclient_no_sudo }}"
all_ip_addresses: "{{ ipaclient_all_ip_addresses }}"
fixed_primary: "{{ ipassd_fixed_primary
| default(ipasssd_fixed_primary) }}"
permit: "{{ ipassd_permit | default(ipasssd_permit) }}"
enable_dns_updates: "{{ ipassd_enable_dns_updates
| default(ipasssd_enable_dns_updates) }}"
preserve_sssd: "{{ ipassd_preserve_sssd
| default(ipasssd_preserve_sssd) }}"
no_krb5_offline_passwords:
"{{ ipassd_no_krb5_offline_passwords
| default(ipasssd_no_krb5_offline_passwords) }}"
- name: Install - IPA API calls for remaining enrollment parts
ipaclient_api:
servers: "{{ result_ipaclient_test.servers }}"
realm: "{{ result_ipaclient_test.realm }}"
hostname: "{{ result_ipaclient_test.hostname }}"
# debug: yes
krb_name: "{{ result_ipaclient_temp_krb5.krb_name }}"
register: result_ipaclient_api
- name: Install - Fix IPA ca
ipaclient_fix_ca:
servers: "{{ result_ipaclient_test.servers }}"
realm: "{{ result_ipaclient_test.realm }}"
basedn: "{{ result_ipaclient_test.basedn }}"
allow_repair: "{{ ipaclient_allow_repair }}"
krb_name: "{{ result_ipaclient_temp_krb5.krb_name }}"
when: not ipaclient_on_master | bool and
result_ipaclient_test_keytab.krb5_keytab_ok and
not result_ipaclient_test_keytab.ca_crt_exists
- name: Install - Create IPA NSS database
ipaclient_setup_nss:
servers: "{{ result_ipaclient_test.servers }}"
domain: "{{ result_ipaclient_test.domain }}"
realm: "{{ result_ipaclient_test.realm }}"
basedn: "{{ result_ipaclient_test.basedn }}"
hostname: "{{ result_ipaclient_test.hostname }}"
subject_base: "{{ result_ipaclient_api.subject_base }}"
principal: "{{ ipaadmin_principal | default(omit) }}"
mkhomedir: "{{ ipaclient_mkhomedir }}"
ca_enabled: "{{ result_ipaclient_api.ca_enabled }}"
on_master: "{{ ipaclient_on_master }}"
dnsok: "{{ result_ipaclient_test.dnsok }}"
enable_dns_updates: "{{ ipassd_enable_dns_updates
| default(ipasssd_enable_dns_updates) }}"
all_ip_addresses: "{{ ipaclient_all_ip_addresses }}"
ip_addresses: "{{ ipaclient_ip_addresses | default(omit) }}"
request_cert: "{{ ipaclient_request_cert }}"
preserve_sssd: "{{ ipassd_preserve_sssd
| default(ipasssd_preserve_sssd) }}"
no_ssh: "{{ ipaclient_no_ssh }}"
no_sshd: "{{ ipaclient_no_sshd }}"
no_sudo: "{{ ipaclient_no_sudo }}"
subid: "{{ ipaclient_subid }}"
fixed_primary: "{{ ipassd_fixed_primary
| default(ipasssd_fixed_primary) }}"
permit: "{{ ipassd_permit | default(ipasssd_permit) }}"
no_krb5_offline_passwords:
"{{ ipassd_no_krb5_offline_passwords
| default(ipasssd_no_krb5_offline_passwords) }}"
no_dns_sshfp: "{{ ipaclient_no_dns_sshfp }}"
nosssd_files: "{{ result_ipaclient_test.nosssd_files }}"
selinux_works: "{{ result_ipaclient_test.selinux_works }}"
krb_name: "{{ result_ipaclient_temp_krb5.krb_name }}"
- name: Install - Configure SSH and SSHD
ipaclient_setup_ssh:
servers: "{{ result_ipaclient_test.servers }}"
sssd: "{{ result_ipaclient_test.sssd }}"
no_ssh: "{{ ipaclient_no_ssh }}"
ssh_trust_dns: "{{ ipaclient_ssh_trust_dns }}"
no_sshd: "{{ ipaclient_no_sshd }}"
- name: Install - Configure automount
ipaclient_setup_automount:
servers: "{{ result_ipaclient_test.servers }}"
sssd: "{{ result_ipaclient_test.sssd }}"
automount_location: "{{ ipaclient_automount_location | default(omit) }}"
- name: Install - Configure firefox
ipaclient_setup_firefox:
firefox_dir: "{{ ipaclient_firefox_dir | default(omit) }}"
domain: "{{ result_ipaclient_test.domain }}"
when: ipaclient_configure_firefox | bool
- name: Install - Configure NIS
ipaclient_setup_nis:
domain: "{{ result_ipaclient_test.domain }}"
nisdomain: "{{ ipaclient_nisdomain | default(omit) }}"
when: not ipaclient_no_nisdomain | bool
- name: Remove temporary krb5.conf
ansible.builtin.file:
path: "{{ result_ipaclient_temp_krb5.krb_name }}"
state: absent
when: result_ipaclient_temp_krb5.krb_name is defined
- name: Install - Configure krb5 for IPA realm
ipaclient_setup_krb5:
realm: "{{ result_ipaclient_test.realm }}"
domain: "{{ result_ipaclient_test.domain }}"
servers: "{{ result_ipaclient_test.servers }}"
kdc: "{{ result_ipaclient_test.kdc }}"
dnsok: "{{ result_ipaclient_test.dnsok }}"
client_domain: "{{ result_ipaclient_test.client_domain }}"
hostname: "{{ result_ipaclient_test.hostname }}"
sssd: "{{ result_ipaclient_test.sssd }}"
force: "{{ ipaclient_force }}"
# on_master: "{{ ipaclient_on_master }}"
when: not ipaclient_on_master | bool
- name: Install - Configure certmonger
ipaclient_setup_certmonger:
realm: "{{ result_ipaclient_test.realm }}"
hostname: "{{ result_ipaclient_test.hostname }}"
subject_base: "{{ result_ipaclient_api.subject_base }}"
ca_enabled: "{{ result_ipaclient_api.ca_enabled }}"
request_cert: "{{ ipaclient_request_cert }}"
when: not ipaclient_on_master | bool
always:
- name: Install - Restore original admin password if overwritten by OTP
no_log: yes
ansible.builtin.set_fact:
ipaadmin_password: "{{ ipaadmin_orig_password }}"
when: ipaclient_use_otp | bool and ipaadmin_orig_password is defined
- name: Cleanup leftover ccache
ansible.builtin.file:
path: "/etc/ipa/.dns_ccache"
state: absent
- name: Remove temporary krb5.conf
ansible.builtin.file:
path: "{{ result_ipaclient_temp_krb5.krb_name }}"
state: absent
when: result_ipaclient_temp_krb5.krb_name is defined
- name: Remove temporary krb5.conf backup
ansible.builtin.file:
path: "{{ result_ipaclient_temp_krb5.krb_name }}.ipabkp"
state: absent
when: result_ipaclient_temp_krb5.krb_name is defined
ansible-freeipa-master/roles/ipaclient/tasks/main.yml 0000664 0000000 0000000 00000002373 14600563364 0023301 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipaclient
- name: Import variables specific to distribution
ansible.builtin.include_vars: "{{ item }}"
with_first_found:
- "{{ role_path }}/vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_version'] }}.yml"
- "{{ role_path }}/vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "{{ role_path }}/vars/{{ ansible_facts['distribution'] }}.yml"
# os_family is used as a fallback for distros which are not currently
# supported, but are based on a supported distro family. For example,
# Oracle, Rocky, Alma and Alibaba linux, which are all "RedHat" based.
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_version'] }}.yml"
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "vars/{{ ansible_facts['os_family'] }}.yml"
# If neither distro nor family is supported, try a default configuration.
- "{{ role_path }}/vars/default.yml"
- name: Install IPA client
ansible.builtin.include_tasks: install.yml
when: state|default('present') == 'present'
- name: Uninstall IPA client
ansible.builtin.include_tasks: uninstall.yml
when: state|default('present') == 'absent'
ansible-freeipa-master/roles/ipaclient/tasks/uninstall.yml 0000664 0000000 0000000 00000001145 14600563364 0024362 0 ustar 00root root 0000000 0000000 ---
# tasks to uninstall IPA client
- name: Uninstall - Uninstall IPA client
ansible.builtin.command: >
/usr/sbin/ipa-client-install
--uninstall
-U
register: uninstall
# 2 means that uninstall failed because IPA client was not configured
failed_when: uninstall.rc != 0 and uninstall.rc != 2
changed_when: uninstall.rc == 0
- name: Uninstall - Unconfigure DNS resolver
ipaclient_configure_dns_resolver:
state: absent
when: ipaclient_cleanup_dns_resolver | bool
#- name: Remove IPA client package
# ansible.builtin.package:
# name: "{{ ipaclient_packages }}"
# state: absent
ansible-freeipa-master/roles/ipaclient/vars/ 0000775 0000000 0000000 00000000000 14600563364 0021453 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaclient/vars/Debian-10.yml 0000664 0000000 0000000 00000000432 14600563364 0023575 0 ustar 00root root 0000000 0000000 ---
# vars/Debian.yml
ipaclient_packages: [ "freeipa-client" ]
# Debian Buster must use python2 as Python interpreter due
# to the way freeipa-client package is defined.
# You must install package python2.7 before executing this role.
ansible_python_interpreter: '/usr/bin/python2'
ansible-freeipa-master/roles/ipaclient/vars/Debian.yml 0000664 0000000 0000000 00000000135 14600563364 0023357 0 ustar 00root root 0000000 0000000 # defaults file for ipaclient
# vars/Debian.yml
---
ipaclient_packages: [ "freeipa-client" ]
ansible-freeipa-master/roles/ipaclient/vars/Fedora-25.yml 0000664 0000000 0000000 00000000241 14600563364 0023617 0 ustar 00root root 0000000 0000000 # defaults file for ipaclient
# vars/Fedora-25.yml
---
ipaclient_packages: [ "ipa-client", "libselinux-python" ]
#ansible_python_interpreter: '/usr/bin/python2'
ansible-freeipa-master/roles/ipaclient/vars/Fedora-26.yml 0000664 0000000 0000000 00000000241 14600563364 0023620 0 ustar 00root root 0000000 0000000 # defaults file for ipaclient
# vars/Fedora-26.yml
---
ipaclient_packages: [ "ipa-client", "libselinux-python" ]
#ansible_python_interpreter: '/usr/bin/python2'
ansible-freeipa-master/roles/ipaclient/vars/RedHat-7.3.yml 0000664 0000000 0000000 00000000264 14600563364 0023654 0 ustar 00root root 0000000 0000000 # defaults file for ipaclient
# vars/RedHat-7.3.yml
---
ipaclient_packages: [ "ipa-client", "ipa-admintools", "libselinux-python" ]
#ansible_python_interpreter: '/usr/bin/python2'
ansible-freeipa-master/roles/ipaclient/vars/RedHat-7.yml 0000664 0000000 0000000 00000000234 14600563364 0023510 0 ustar 00root root 0000000 0000000 # defaults file for ipaclient
# vars/RedHat-7
---
ipaclient_packages: [ "ipa-client", "libselinux-python" ]
#ansible_python_interpreter: '/usr/bin/python2'
ansible-freeipa-master/roles/ipaclient/vars/RedHat-8.yml 0000664 0000000 0000000 00000000140 14600563364 0023505 0 ustar 00root root 0000000 0000000 # defaults file for ipaclient
# vars/RedHat-8.yml
---
ipaclient_packages: [ "@idm:DL1/client" ]
ansible-freeipa-master/roles/ipaclient/vars/Ubuntu-18.04.yml 0000664 0000000 0000000 00000000451 14600563364 0024130 0 ustar 00root root 0000000 0000000 # vars/Ubuntu-18.04.yml
---
ipaclient_packages: [ "freeipa-client" ]
# Ubuntu Bionic Beaver must use python2 as Python interpreter due
# to the way python-ipalib package is defined.
# Package python2.7 must be installed before executing this role.
ansible_python_interpreter: '/usr/bin/python2.7'
ansible-freeipa-master/roles/ipaclient/vars/default.yml 0000664 0000000 0000000 00000000240 14600563364 0023616 0 ustar 00root root 0000000 0000000 # defaults file for ipaclient
# vars/default.yml
---
ipaclient_packages: [ "ipa-client", "python3-libselinux" ]
#ansible_python_interpreter: '/usr/bin/python3'
ansible-freeipa-master/roles/ipareplica/ 0000775 0000000 0000000 00000000000 14600563364 0020641 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipareplica/README.md 0000664 0000000 0000000 00000033147 14600563364 0022130 0 ustar 00root root 0000000 0000000 ipareplica role
==============
Description
-----------
This role allows to configure a new IPA server that is a replica of the server. Once it has been created it is an exact copy of the original IPA server and is an equal master.
Changes made to any master are automatically replicated to other masters.
This can be done in different ways using auto-discovery of the servers, domain and other settings or by specifying them.
**Note**: The ansible playbooks and role require a configured ansible environment where the ansible nodes are reachable and are properly set up to have an IP address and a working package manager.
Features
--------
* Replica deployment
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.6 and up are supported by the replica role.
Supported Distributions
-----------------------
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
* Ubuntu 16.04 and 18.04
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
* Supported distribution (needed for package installation only, see above)
Usage
=====
Example inventory file with fixed principal using auto-discovery with DNS records:
```ini
[ipareplicas]
ipareplica1.example.com
ipareplica2.example.com
[ipareplicas:vars]
ipaadmin_principal=admin
```
Example playbook to setup the IPA client(s) using principal from inventory file and password from an [Ansible Vault](http://docs.ansible.com/ansible/latest/playbooks_vault.html) file:
```yaml
---
- name: Playbook to configure IPA replicas
hosts: ipareplicas
become: true
vars_files:
- playbook_sensitive_data.yml
roles:
- role: ipareplica
state: present
```
Example playbook to unconfigure the IPA client(s) using principal and password from inventory file:
```yaml
---
- name: Playbook to unconfigure IPA replicas
hosts: ipareplicas
become: true
roles:
- role: ipareplica
state: absent
```
Example inventory file with fixed server, principal, password and domain:
```ini
[ipaserver]
ipaserver.example.com
[ipareplicas]
ipareplica1.example.com
ipareplica2.example.com
[ipareplicas:vars]
ipareplica_domain=example.com
ipaadmin_principal=admin
ipaadmin_password=MySecretPassword123
ipadm_password=MySecretPassword456
```
Example playbook to setup the IPA client(s) using principal and password from inventory file:
```yaml
---
- name: Playbook to configure IPA replicas with username/password
hosts: ipareplicas
become: true
roles:
- role: ipareplica
state: present
```
Example inventory file to remove a replica from the domain:
```ini
[ipareplicas]
ipareplica1.example.com
[ipareplicas:vars]
ipaadmin_password=MySecretPassword123
ipareplica_remove_from_domain=true
```
Example playbook to remove an IPA replica using admin passwords from the domain:
```yaml
---
- name: Playbook to remove IPA replica
hosts: ipareplica
become: true
roles:
- role: ipareplica
state: absent
```
The inventory will enable the removal of the replica (also a replica) from the domain. Additional options are needed if the removal of the replica is resulting in a topology disconnect or if the replica is the last that has a role.
To continue with the removal with a topology disconnect it is needed to set these parameters:
```ini
ipareplica_ignore_topology_disconnect=true
ipareplica_remove_on_server=ipareplica2.example.com
```
To continue with the removal for a replica that is the last that has a role:
```ini
ipareplica_ignore_last_of_role=true
```
Be careful with enabling the `ipareplica_ignore_topology_disconnect` and especially `ipareplica_ignore_last_of_role`, the change can not be reverted easily.
The parameters `ipaserver_ignore_topology_disconnect`, `ipaserver_ignore_last_of_role`, `ipaserver_remove_on_server` and `ipaserver_remove_from_domain` can be used instead.
Playbooks
=========
The playbooks needed to deploy or undeploy a replica are part of the repository in the playbooks folder. There are also playbooks to deploy and undeploy clusters.
```
install-replica.yml
uninstall-replica.yml
```
Please remember to link or copy the playbooks to the base directory of ansible-freeipa if you want to use the roles within the source archive.
How to setup replicas
---------------------
```bash
ansible-playbook -v -i inventory/hosts install-replica.yml
```
This will deploy the replicas defined in the inventory file.
Variables
=========
Base Variables
--------------
Variable | Description | Required
-------- | ----------- | --------
`ipaservers` | This group with the IPA master full qualified hostnames. (list of strings) | mostly
`ipareplicas` | Group of IPA replica hostnames. (list of strings) | yes
`ipaadmin_password` | The password for the IPA admin user (string) | mostly
`ipareplica_ip_addresses` | The list of master server IP addresses. (list of strings) | no
`ipareplica_domain` | The primary DNS domain of an existing IPA deployment. (string) | no
`ipaserver_realm` | The Kerberos realm of an existing IPA deployment. (string) | no
`ipaserver_hostname` | Fully qualified name of the server. (string) | no
`ipaadmin_principal` | The authorized kerberos principal used to join the IPA realm. (string) | no
`ipareplica_no_host_dns` | Do not use DNS for hostname lookup during installation. (bool, default: false) | no
`ipareplica_skip_conncheck` | Skip connection check to remote master. (bool, default: false) | no
`ipareplica_pki_config_override` | Path to ini file with config overrides. This is only usable with recent FreeIPA versions. (string) | no
`ipareplica_mem_check` | Checking for minimum required memory for the deployment. This is only usable with recent FreeIPA versions (4.8.10+) else ignored. (bool, default: yes) | no
Server Variables
----------------
Variable | Description | Required
-------- | ----------- | --------
`ipadm_password` | The password for the Directory Manager. (string) | mostly
`ipareplica_hidden_replica` | Install a hidden replica. (bool, default: false) | no
`ipareplica_setup_adtrust` | Configure AD trust capability. (bool, default: false) | no
`ipareplica_setup_ca` | Configure a dogtag CA. (bool, default: false) | no
`ipareplica_setup_kra` | Configure a dogtag KRA. (bool, default: false) | no
`ipareplica_setup_dns` | Configure bind with our zone. (bool, default: false) | no
`ipareplica_no_pkinit` | Disables pkinit setup steps. (bool, default: false) | no
`ipareplica_no_ui_redirect` | Do not automatically redirect to the Web UI. (bool, default: false) | no
`ipareplica_dirsrv_config_file` | The path to LDIF file that will be used to modify configuration of dse.ldif during installation of the directory server instance. (string)| no
SSL certificate Variables
-------------------------
Variable | Description | Required
-------- | ----------- | --------
`ipareplica_dirsrv_cert_files` | Files containing the Directory Server SSL certificate and private keys. (list of strings) | no
`ipareplica_http_cert_files` | Files containing the Apache Server SSL certificate and private key. (list of string) | no
`ipareplica_pkinit_cert_files` | Files containing the Kerberos KDC SSL certificate and private key. (list of string) | no
`ipareplica_dirsrv_pin` | The password to unlock the Directory Server private key. (string) | no
`ipareplica_http_pin` | The password to unlock the Apache Server private key. (string) | no
`ipareplica_pkinit_pin` | The password to unlock the Kerberos KDC private key. (string) | no
`ipareplica_dirsrv_cert_name` | Name of the Directory Server SSL certificate to install. (string) | no
`ipareplica_http_cert_name` | Name of the Apache Server SSL certificate to install. (string) | no
`ipareplica_pkinit_cert_name` | Name of the Kerberos KDC SSL certificate to install. (string) | no
Client Variables
----------------
Variable | Description | Required
-------- | ----------- | --------
`ipaclient_keytab` | Path to backed up keytab from previous enrollment. (string) | no
`ipaclient_mkhomedir` | Set to yes to configure PAM to create a users home directory if it does not exist. (string) | no
`ipaclient_force_join` | Force client enrollment even if already enrolled. (bool, default: false) | no
`ipaclient_ntp_servers` | The list defines the NTP servers to be used. (list of strings) | no
`ipaclient_ntp_pool` | The string value defines the ntp server pool to be used. (string) | no
`ipaclient_no_ntp` | The bool value defines if NTP will not be configured and enabled. (bool, default: false) | no
`ipaclient_ssh_trust_dns` | The bool value defines if OpenSSH client will be configured to trust DNS SSHFP records. (bool, default: false) | no
`ipaclient_no_ssh` | The bool value defines if OpenSSH client will be configured. (bool, default: false) | no
`ipaclient_no_sshd` | The bool value defines if OpenSSH server will be configured. (bool, default: false) | no
`ipaclient_no_sudo` | The bool value defines if SSSD will be configured as a data source for sudo. (bool, default: false) | no
`ipaclient_subid` | The bool value defines if SSSD will be configured as a data source for subid. (bool, default: false) | no
`ipaclient_no_dns_sshfp` | The bool value defines if DNS SSHFP records will not be created automatically. (bool, default: false) | no
Certificate system Variables
----------------------------
Variable | Description | Required
-------- | ----------- | --------
~~`ipareplica_skip_schema_check`~~ | ~~Skip check for updated CA DS schema on the remote master. (bool, default: false)~~ | ~~no~~
DNS Variables
-------------
Variable | Description | Required
-------- | ----------- | --------
`ipareplica_allow_zone_overlap` | Allow creation of (reverse) zone even if the zone is already resolvable. (bool, default: false) | no
`ipareplica_reverse_zones` | The reverse DNS zones to use. (list of strings) | no
`ipareplica_no_reverse` | Do not create reverse DNS zone. (bool, default: false) | no
`ipareplica_auto_reverse` | Try to resolve reverse records and reverse zones for server IP addresses. (bool, default: false) | no
`ipareplica_zonemgr` | The e-mail address of the DNS zone manager. (string, default: hostmaster@DOMAIN.) | no
`ipareplica_forwarders` | Add DNS forwarders to the DNS configuration. (list of strings) | no
`ipareplica_no_forwarders` | Do not add any DNS forwarders. Root DNS servers will be used instead. (bool, default: false) | no
`ipareplica_auto_forwarders` | Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS. (bool, default: false) | no
`ipareplica_forward_policy` | DNS forwarding policy for global forwarders specified using other options. (choice: first,only) | no
`ipareplica_no_dnssec_validation` | Disable DNSSEC validation on this server. (bool, default: false) | no
AD trust Variables
------------------
Variable | Description | Required
-------- | ----------- | --------
~~`ipareplica_add_sids`~~ | ~~Add SIDs for existing users and groups as the final step. (bool, default: false)~~ | ~~no~~
~~`ipareplica_add_agents`~~ | ~~Add IPA masters to a list of hosts allowed to serve information about users from trusted forests. (bool, default: false)~~ | ~~no~~
`ipareplica_enable_compat`| Enables support for trusted domains users for old clients through Schema Compatibility plugin. (bool, default: false) | no
`ipareplica_netbios_name` | The NetBIOS name for the IPA domain. (string) | no
`ipareplica_rid_base` | First RID value of the local domain. (integer) | no
`ipareplica_secondary_rid_base` | Start value of the secondary RID range. (integer) | no
Cluster Specific Variables
--------------------------
Variable | Description | Required
-------- | ----------- | --------
`ipareplica_servers` | Manually override list of servers for example in a cluster environment on a per replica basis. The list of servers is normally taken from from groups.ipaserver in cluster environments. (list of strings) | no
`ipaserver_domain` | Used if set in a cluster environment to overload `ipareplica_domain` | no
Special Variables
-----------------
Variable | Description | Required
-------- | ----------- | --------
`ipareplica_install_packages` | The bool value defines if the needed packages are installed on the node. (bool, default: true) | no
`ipareplica_setup_firewalld` | The value defines if the needed services will automatically be openen in the firewall managed by firewalld. (bool, default: true) | no
`ipareplica_firewalld_zone` | The value defines the firewall zone that will be used. This needs to be an existing runtime and permanent zone. (string) | no
Undeploy Variables (`state`: absent)
------------------------------------
These settings should only be used if the result is really wanted. The change might not be revertable easily.
Variable | Description | Required
-------- | ----------- | --------
`ipareplica_ignore_topology_disconnect` \| `ipaserver_ignore_topology_disconnect` | If enabled this enforces the removal of the replica even if it results in a topology disconnect. Be careful with this setting. (bool) | false
`ipareplica_ignore_last_of_role` \| `ipaserver_ignore_last_of_role` | If enabled this enforces the removal of the replica even if the replica is the last with one that has a role. Be careful, this might not be revered easily. (bool) | false
`ipareplica_remove_from_domain` \| `ipaserver_remove_from_domain` | This enables the removal of the replica from the domain additionally to the undeployment. (bool) | false
`ipareplica_remove_on_server` \| `ipaserver_remove_on_server` | The value defines the replica in the domain that will to be used to remove the replica from the domain if `ipareplica_ignore_topology_disconnect` and `ipareplica_remove_from_domain` are enabled. Without the need to enable `ipareplica_ignore_topology_disconnect`, the value will be automatically detected using the replication agreements of the replica. (string) | false
Authors
=======
Thomas Woerner
ansible-freeipa-master/roles/ipareplica/defaults/ 0000775 0000000 0000000 00000000000 14600563364 0022450 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipareplica/defaults/main.yml 0000664 0000000 0000000 00000002053 14600563364 0024117 0 ustar 00root root 0000000 0000000 ---
# defaults file for ipareplica
### basic ###
ipareplica_no_host_dns: no
ipareplica_skip_conncheck: no
ipareplica_hidden_replica: no
ipareplica_mem_check: yes
### server ###
ipareplica_setup_adtrust: no
ipareplica_setup_ca: no
ipareplica_setup_kra: no
ipareplica_setup_dns: no
ipareplica_no_pkinit: no
ipareplica_no_ui_redirect: no
### client ###
ipaclient_mkhomedir: no
ipaclient_force_join: no
ipaclient_no_ntp: no
#ipaclient_ssh_trust_dns: no
#ipaclient_no_ssh: no
#ipaclient_no_sshd: no
#ipaclient_no_dns_sshfp: no
ipaclient_ssh_trust_dns: no
### certificate system ###
ipareplica_skip_schema_check: no
### dns ###
ipareplica_allow_zone_overlap: no
ipareplica_no_reverse: no
ipareplica_auto_reverse: no
ipareplica_no_forwarders: no
ipareplica_auto_forwarders: no
ipareplica_no_dnssec_validation: no
### ad trust ###
ipareplica_enable_compat: no
### uninstall ###
ipareplica_ignore_topology_disconnect: no
ipareplica_ignore_last_of_role: no
### additional ###
### packages ###
ipareplica_install_packages: yes
### firewalld ###
ipareplica_setup_firewalld: yes
ansible-freeipa-master/roles/ipareplica/library/ 0000775 0000000 0000000 00000000000 14600563364 0022305 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipareplica/library/ipareplica_add_to_ipaservers.py 0000664 0000000 0000000 00000010225 14600563364 0030545 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_add_to_ipaservers
short_description: Add to ipaservers
description:
Add to ipaservers
options:
setup_kra:
description: Configure a dogtag KRA
type: bool
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
installer_ccache:
description: The installer ccache setting
type: str
required: yes
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_remote_api, api
)
from ansible.module_utils import six
if six.PY3:
unicode = str
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_kra=dict(required=True, type='bool'),
# additional
config_master_host_name=dict(required=True, type='str'),
ccache=dict(required=True, type='str'),
installer_ccache=dict(required=True, type='str'),
_top_dir=dict(required=True, type='str'),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# server
options.setup_kra = ansible_module.params.get('setup_kra')
# additional
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._ccache = ansible_module.params.get('installer_ccache')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
options._top_dir = ansible_module.params.get('_top_dir')
# init #
ansible_log.debug("== INSTALLER ==")
options = installer
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
# config = gen_ReplicaConfig()
remote_api = gen_remote_api(config_master_host_name, paths.ETC_IPA)
# installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
ansible_log.debug("-- HOSTGROUP_ADD_MEMBER --")
try:
ansible_log.debug("-- CONNECT --")
conn.connect(ccache=installer._ccache)
remote_api.Command['hostgroup_add_member'](
u'ipaservers',
host=[unicode(api.env.host)],
)
finally:
if conn.isconnected():
ansible_log.debug("-- DISCONNECT --")
conn.disconnect()
os.environ['KRB5CCNAME'] = ccache
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_create_ipa_conf.py 0000664 0000000 0000000 00000025050 14600563364 0030153 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_create_ipa_conf
short_description: Create ipa.conf
description:
Create ipa.conf
options:
dm_password:
description: Directory Manager password
type: str
required: no
password:
description: Admin user kerberos password
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: no
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: no
hostname:
description: Fully qualified name of this host
type: str
required: no
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
type: list
elements: str
required: no
no_host_dns:
description: Do not use DNS for hostname lookup during installation
type: bool
default: no
required: no
setup_adtrust:
description: Configure AD trust capability
type: bool
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
setup_dns:
description: Configure bind with our zone
type: bool
required: no
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
type: list
elements: str
required: no
force_join:
description: Force client enrollment even if already enrolled
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
server:
description: Fully qualified name of IPA server to enroll to
type: str
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
config_ca_host_name:
description: The config ca_host_name setting
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
installer_ccache:
description: The installer ccache setting
type: str
required: yes
_ca_enabled:
description: The installer _ca_enabled setting
type: bool
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
_add_to_ipaservers:
description: The installer _add_to_ipaservers setting
type: bool
required: yes
_ca_subject:
description: The installer _ca_subject setting
type: str
required: yes
_subject_base:
description: The installer _subject_base setting
type: str
required: yes
master:
description: Master host name
type: str
required: no
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
ansible_module_get_parsed_ip_addresses, sysrestore,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, create_ipa_conf
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=False, type='str', no_log=True),
password=dict(required=False, type='str', no_log=True),
ip_addresses=dict(required=False, type='list', elements='str',
default=[]),
domain=dict(required=False, type='str'),
realm=dict(required=False, type='str'),
hostname=dict(required=False, type='str'),
ca_cert_files=dict(required=False, type='list', elements='str',
default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
# server
setup_adtrust=dict(required=False, type='bool'),
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
setup_dns=dict(required=False, type='bool'),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', elements='str',
default=[]),
# client
force_join=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
server=dict(required=True, type='str'),
config_master_host_name=dict(required=True, type='str'),
config_ca_host_name=dict(required=True, type='str'),
ccache=dict(required=True, type='str'),
installer_ccache=dict(required=True, type='str'),
_ca_enabled=dict(required=False, type='bool'),
_top_dir=dict(required=True, type='str'),
_add_to_ipaservers=dict(required=True, type='bool'),
_ca_subject=dict(required=True, type='str'),
_subject_base=dict(required=True, type='str'),
master=dict(required=False, type='str', default=None),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
options.dm_password = ansible_module.params.get('dm_password')
options.password = options.dm_password
options.admin_password = ansible_module.params.get('password')
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.no_host_dns = ansible_module.params.get('no_host_dns')
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
# client
options.force_join = ansible_module.params.get('force_join')
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options.ca_subject = ansible_module.params.get('ca_subject')
# additional
# options._host_name_overridden = ansible_module.params.get(
# '_hostname_overridden')
options.server = ansible_module.params.get('server')
master_host_name = ansible_module.params.get('config_master_host_name')
ca_host_name = ansible_module.params.get('config_ca_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options._top_dir = ansible_module.params.get('_top_dir')
options._add_to_ipaservers = ansible_module.params.get(
'_add_to_ipaservers')
options._ca_subject = ansible_module.params.get('_ca_subject')
options._subject_base = ansible_module.params.get('_subject_base')
master = ansible_module.params.get('master')
dirman_password = ansible_module.params.get('dirman_password')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
# prepare (install prepare, install checks) #
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.subject_base = options.subject_base
config.dirman_password = dirman_password
config.ca_host_name = ca_host_name
config.setup_ca = options.setup_ca
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
ccache = os.environ['KRB5CCNAME']
if promote:
ansible_log.debug("-- CREATE_IPA_CONF --")
# Create the management framework config file. Do this irregardless
# of the state of DS installation. Even if it fails,
# we need to have master-like configuration in order to perform a
# successful uninstallation
# The configuration creation has to be here otherwise previous call
# To config certmonger would try to connect to local server
create_ipa_conf(fstore, config, ca_enabled, master)
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_custodia_import_dm_password.py 0000664 0000000 0000000 00000016434 14600563364 0032667 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_custodia_import_dm_password
short_description: Import dm password into custodia
description:
Import dm password into custodia
options:
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
required: no
no_ui_redirect:
description: Do not automatically redirect to the Web UI
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_ca_enabled:
description: The installer _ca_enabled setting
type: bool
required: no
_ca_file:
description: The installer _ca_file setting
type: str
required: no
_kra_enabled:
description: The installer _kra_enabled setting
type: bool
required: no
_kra_host_name:
description: The installer _kra_host_name setting
type: str
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
config_setup_ca:
description: The config setup_ca setting
type: bool
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
config_ca_host_name:
description: The config ca_host_name setting
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, redirect_stdout, custodiainstance,
getargspec
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
ccache=dict(required=True, type='str'),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False, type='str'),
_kra_enabled=dict(required=False, type='bool'),
_kra_host_name=dict(required=False, type='str'),
_top_dir=dict(required=True, type='str'),
dirman_password=dict(required=True, type='str', no_log=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True, type='str'),
config_ca_host_name=dict(required=True, type='str'),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
kra_enabled = ansible_module.params.get('_kra_enabled')
kra_host_name = ansible_module.params.get('_kra_host_name')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
config_setup_ca = ansible_module.params.get('config_setup_ca')
config_ca_host_name = ansible_module.params.get('config_ca_host_name')
# init #
ansible_log.debug("== INSTALL ==")
options = installer
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.dirman_password = dirman_password
config.setup_ca = config_setup_ca
config.master_host_name = master_host_name
config.ca_host_name = config_ca_host_name
config.subject_base = options.subject_base
config.promote = installer.promote
config.kra_enabled = kra_enabled
config.kra_host_name = kra_host_name
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
ccache = os.environ['KRB5CCNAME']
# do the work #
with redirect_stdout(ansible_log):
if not hasattr(custodiainstance, "get_custodia_instance"):
custodia = custodiainstance.CustodiaInstance(config.host_name,
config.realm_name)
else:
if ca_enabled:
mode = custodiainstance.CustodiaModes.CA_PEER
else:
mode = custodiainstance.CustodiaModes.MASTER_PEER
custodia = custodiainstance.get_custodia_instance(config, mode)
ansible_log.debug("-- CUSTODIA IMPORT DM PASSWORD --")
# pylint: disable=deprecated-method
argspec = getargspec(custodia.import_dm_password)
# pylint: enable=deprecated-method
if "master_host_name" in argspec.args:
custodia.import_dm_password(config.master_host_name)
else:
custodia.import_dm_password()
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_ds_apply_updates.py 0000664 0000000 0000000 00000017516 14600563364 0030422 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_ds_apply_updates
short_description: DS apply updates
description:
DS apply updates
options:
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
required: no
no_ui_redirect:
description: Do not automatically redirect to the Web UI
type: bool
required: no
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
type: str
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_ca_enabled:
description: The installer _ca_enabled setting
type: bool
required: no
_ca_file:
description: The installer _ca_file setting
type: str
required: no
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
type: list
elements: str
required: no
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
type: list
elements: str
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
ds_ca_subject:
description: The ds.ca_subject setting
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout,
replica_ds_init_info, dsinstance, upgradeinstance, installutils
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
dirsrv_config_file=dict(required=False, type='str'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
config_master_host_name=dict(required=True, type='str'),
ccache=dict(required=True, type='str'),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False, type='str'),
_dirsrv_pkcs12_info=dict(required=False, type='list',
elements='str'),
_pkinit_pkcs12_info=dict(required=False, type='list',
elements='str'),
_top_dir=dict(required=True, type='str'),
dirman_password=dict(required=True, type='str', no_log=True),
ds_ca_subject=dict(required=True, type='str'),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
installer._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
installer._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
ds_ca_subject = ansible_module.params.get('ds_ca_subject')
# init #
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.dirman_password = dirman_password
config.subject_base = options.subject_base
config.master_host_name = master_host_name
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
api.Backend.ldap2.connect()
conn.connect(ccache=ccache)
with redirect_stdout(ansible_log):
ds = replica_ds_init_info(ansible_log,
config, options, ca_enabled,
remote_api, ds_ca_subject,
ca_file=paths.IPA_CA_CRT,
promote=promote,
pkcs12_info=installer._dirsrv_pkcs12_info)
ansible_log.debug("-- DS APPLY_UPDATES --")
# Apply any LDAP updates. Needs to be done after the replica is
# synced-up
# service.print_msg("Applying LDAP updates")
# ds.apply_updates()
schema_files = dsinstance.get_all_external_schema_files(
paths.EXTERNAL_SCHEMA_DIR)
data_upgrade = upgradeinstance.IPAUpgrade(ds.realm,
schema_files=schema_files)
data_upgrade.set_output(ansible_log)
try:
data_upgrade.create_instance()
except Exception as e:
# very fatal errors only will raise exception
raise RuntimeError("Update failed: %s" % e)
installutils.store_version()
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_ds_enable_ssl.py 0000664 0000000 0000000 00000016033 14600563364 0027650 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_ds_enable_ssl
short_description: DS enable SSL
description:
DS enable SSL
options:
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
required: no
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
type: str
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_ca_enabled:
description: The installer _ca_enabled setting
type: bool
required: no
_ca_file:
description: The installer _ca_file setting
type: str
required: no
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
type: list
elements: str
required: no
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
type: list
elements: str
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
ds_ca_subject:
description: The ds.ca_subject setting
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout,
replica_ds_init_info
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
dirsrv_config_file=dict(required=False, type='str'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
config_master_host_name=dict(required=True, type='str'),
ccache=dict(required=True, type='str'),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False, type='str'),
_dirsrv_pkcs12_info=dict(required=False, type='list',
elements='str'),
_pkinit_pkcs12_info=dict(required=False, type='list',
elements='str'),
_top_dir=dict(required=True, type='str'),
dirman_password=dict(required=True, type='str', no_log=True),
ds_ca_subject=dict(required=True, type='str'),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
options._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
options._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
ds_ca_subject = ansible_module.params.get('ds_ca_subject')
# init #
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.dirman_password = dirman_password
config.subject_base = options.subject_base
config.master_host_name = master_host_name
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
# installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
api.Backend.ldap2.connect()
conn.connect(ccache=ccache)
with redirect_stdout(ansible_log):
ds = replica_ds_init_info(ansible_log,
config, options, ca_enabled,
remote_api, ds_ca_subject,
ca_file=paths.IPA_CA_CRT,
promote=promote,
pkcs12_info=installer._dirsrv_pkcs12_info)
ansible_log.debug("-- DS.ENABLE_SSL --")
# we now need to enable ssl on the ds
ds.enable_ssl()
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_enable_ipa.py 0000664 0000000 0000000 00000013134 14600563364 0027131 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_enable_ipa
short_description: Enable IPA
description: Enable IPA
Enable IPA
options:
hostname:
description: Fully qualified name of this host
type: str
required: no
hidden_replica:
description: Install a hidden replica
type: bool
default: no
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
setup_ca:
description: Configure a dogtag CA
type: bool
required: yes
setup_kra:
description: Configure a dogtag KRA
type: bool
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, service,
find_providing_servers, services
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
hostname=dict(required=False, type='str'),
hidden_replica=dict(required=False, type='bool', default=False),
# server
# certificate system
subject_base=dict(required=True, type='str'),
# additional
ccache=dict(required=True, type='str'),
_top_dir=dict(required=True, type='str'),
setup_ca=dict(required=True, type='bool'),
setup_kra=dict(required=True, type='bool'),
config_master_host_name=dict(required=True, type='str'),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
options.host_name = ansible_module.params.get('hostname')
options.hidden_replica = ansible_module.params.get('hidden_replica')
# server
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._top_dir = ansible_module.params.get('_top_dir')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
# init #
ansible_log.debug("== INSTALL ==")
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
remote_api = gen_remote_api(config_master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
ccache = os.environ['KRB5CCNAME']
api.Backend.ldap2.connect()
with redirect_stdout(ansible_log):
if options.hidden_replica:
# Set services to hidden
service.hide_services(config.host_name)
else:
# Enable configured services
service.enable_services(config.host_name)
# update DNS SRV records. Although it's only really necessary in
# enabled-service case, also perform update in hidden replica case.
api.Command.dns_update_system_records()
ca_servers = find_providing_servers('CA', api.Backend.ldap2, api=api)
api.Backend.ldap2.disconnect()
# Everything installed properly, activate ipa service.
services.knownservices.ipa.enable()
# Print a warning if CA role is only installed on one server
if len(ca_servers) == 1:
msg = u'''
WARNING: The CA service is only installed on one server ({0}).
It is strongly recommended to install it on another server.
Run ipa-ca-install(1) on another master to accomplish this.
'''.format(ca_servers[0])
ansible_module.debug(msg)
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_install_ca_certs.py 0000664 0000000 0000000 00000027036 14600563364 0030371 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_install_ca_certs
short_description: Install CA certs
description:
Install CA certs
options:
dm_password:
description: Directory Manager password
type: str
required: no
password:
description: Admin user kerberos password
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: no
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: no
hostname:
description: Fully qualified name of this host
type: str
required: no
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
type: list
elements: str
required: no
no_host_dns:
description: Do not use DNS for hostname lookup during installation
type: bool
default: no
required: no
setup_adtrust:
description: Configure AD trust capability
type: bool
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
setup_dns:
description: Configure bind with our zone
type: bool
required: no
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
type: list
elements: str
required: no
force_join:
description: Force client enrollment even if already enrolled
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
server:
description: Fully qualified name of IPA server to enroll to
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
installer_ccache:
description: The installer ccache setting
type: str
required: yes
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
_add_to_ipaservers:
description: The installer _add_to_ipaservers setting
type: bool
required: yes
_ca_subject:
description: The installer _ca_subject setting
type: str
required: yes
_subject_base:
description: The installer _subject_base setting
type: str
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
config_setup_ca:
description: The config setup_ca setting
type: bool
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
config_ca_host_name:
description: The config ca_host_name setting
type: str
required: yes
config_ips:
description: The config ips setting
type: list
elements: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
ansible_module_get_parsed_ip_addresses,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, ipaldap,
install_ca_cert
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=False, type='str', no_log=True),
password=dict(required=False, type='str', no_log=True),
ip_addresses=dict(required=False, type='list', elements='str',
default=[]),
domain=dict(required=False, type='str'),
realm=dict(required=False, type='str'),
hostname=dict(required=False, type='str'),
ca_cert_files=dict(required=False, type='list', elements='str',
default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
# server
setup_adtrust=dict(required=False, type='bool'),
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
setup_dns=dict(required=False, type='bool'),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', elements='str',
default=[]),
# client
force_join=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
server=dict(required=True, type='str'),
ccache=dict(required=True, type='str'),
installer_ccache=dict(required=True, type='str'),
_top_dir=dict(required=True, type='str'),
_add_to_ipaservers=dict(required=True, type='bool'),
_ca_subject=dict(required=True, type='str'),
_subject_base=dict(required=True, type='str'),
dirman_password=dict(required=True, type='str', no_log=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True, type='str'),
config_ca_host_name=dict(required=True, type='str'),
config_ips=dict(required=False, type='list', elements='str',
default=[]),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# basic
options.dm_password = ansible_module.params.get('dm_password')
options.password = options.dm_password
options.admin_password = ansible_module.params.get('password')
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.no_host_dns = ansible_module.params.get('no_host_dns')
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
# client
options.force_join = ansible_module.params.get('force_join')
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options.ca_subject = ansible_module.params.get('ca_subject')
# additional
options.server = ansible_module.params.get('server')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
installer._ccache = ansible_module.params.get('installer_ccache')
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options._top_dir = ansible_module.params.get('_top_dir')
options._add_to_ipaservers = ansible_module.params.get(
'_add_to_ipaservers')
options._ca_subject = ansible_module.params.get('_ca_subject')
options._subject_base = ansible_module.params.get('_subject_base')
dirman_password = ansible_module.params.get('dirman_password')
config_setup_ca = ansible_module.params.get('config_setup_ca')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
config_ca_host_name = ansible_module.params.get('config_ca_host_name')
config_ips = ansible_module_get_parsed_ip_addresses(ansible_module,
"config_ips")
# init #
ansible_log.debug("== INSTALLER ==")
options = installer
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.dirman_password = dirman_password
config.setup_ca = config_setup_ca
config.master_host_name = config_master_host_name
config.ca_host_name = config_ca_host_name
config.ips = config_ips
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
cafile = paths.IPA_CA_CRT
with redirect_stdout(ansible_log):
try:
ansible_log.debug("-- CONNECT --")
if promote:
conn.connect(ccache=ccache)
else:
# dmlvl 0 replica install should always use DM credentials
# to create remote LDAP connection. Since ACIs permitting hosts
# to manage their own services were added in 4.2 release,
# the master denies this operations.
conn.connect(bind_dn=ipaldap.DIRMAN_DN, cacert=cafile,
bind_pw=dirman_password)
ansible_log.debug("-- INSTALL_CA_CERT --")
# Update and istall updated CA file
cafile = install_ca_cert(conn, api.env.basedn, api.env.realm,
cafile)
install_ca_cert(conn, api.env.basedn, api.env.realm, cafile,
destfile=paths.KDC_CA_BUNDLE_PEM)
install_ca_cert(conn, api.env.basedn, api.env.realm, cafile,
destfile=paths.CA_BUNDLE_PEM)
finally:
if conn.isconnected():
ansible_log.debug("-- DISCONNECT --")
conn.disconnect()
# done #
ansible_module.exit_json(changed=True,
config_master_host_name=config.master_host_name,
config_ca_host_name=config.ca_host_name)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_krb_enable_ssl.py 0000664 0000000 0000000 00000014021 14600563364 0030013 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_krb_enable_ssl
short_description: KRB enable SSL
description:
KRB enable SSL
options:
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_ca_enabled:
description: The installer _ca_enabled setting
type: bool
required: no
_ca_file:
description: The installer _ca_file setting
type: str
required: no
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
type: list
elements: str
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports,
AnsibleModuleLog, setup_logging, installer, DN, paths, sysrestore,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, krbinstance, redirect_stdout
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
config_master_host_name=dict(required=True, type='str'),
ccache=dict(required=True, type='str'),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False, type='str'),
_pkinit_pkcs12_info=dict(required=False, type='list',
elements='str'),
_top_dir=dict(required=True, type='str'),
dirman_password=dict(required=True, type='str', no_log=True),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
options._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.dirman_password = dirman_password
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
# installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
api.Backend.ldap2.connect()
conn.connect(ccache=ccache)
# krb
krb = krbinstance.KrbInstance(fstore)
krb.set_output(ansible_log)
with redirect_stdout(ansible_log):
krb.init_info(api.env.realm, api.env.host,
setup_pkinit=not options.no_pkinit,
subject_base=options.subject_base)
krb.pkcs12_info = options._pkinit_pkcs12_info
krb.master_fqdn = master_host_name
ansible_log.debug("-- KRB ENABLE_SSL --")
# configure PKINIT now that all required services are in place
krb.enable_ssl()
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_master_password.py 0000664 0000000 0000000 00000004306 14600563364 0030270 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-server-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_master_password
short_description: Generate kerberos master password if not given
description:
Generate kerberos master password if not given
options:
master_password:
description: kerberos master password (normally autogenerated)
type: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
password:
description: The master password
type: str
returned: always
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, setup_logging, ipa_generate_password
)
def main():
module = AnsibleModule(
argument_spec=dict(
# basic
master_password=dict(required=False, type='str', no_log=True),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
master_password = module.params.get('master_password')
if not master_password:
master_password = ipa_generate_password()
module.exit_json(changed=True,
password=master_password)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_prepare.py 0000664 0000000 0000000 00000105264 14600563364 0026516 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_prepare
short_description: Prepare ipa replica installation
description: |
Prepare ipa replica installation: Create IPA configuration file, run install
checks again and also update the host name and the hosts file if needed.
The tests and also the results from ipareplica_test are needed.
options:
dm_password:
description: Directory Manager password
type: str
required: no
password:
description: Admin user kerberos password
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: no
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: no
hostname:
description: Fully qualified name of this host
type: str
required: no
principal:
description:
User Principal allowed to promote replicas and join IPA realm
type: str
required: yes
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
type: list
elements: str
required: no
no_host_dns:
description: Do not use DNS for hostname lookup during installation
type: bool
default: no
required: no
setup_adtrust:
description: Configure AD trust capability
type: bool
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
setup_dns:
description: Configure bind with our zone
type: bool
required: no
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
type: list
elements: str
required: no
dirsrv_cert_name:
description: Name of the Directory Server SSL certificate to install
type: str
required: no
dirsrv_pin:
description: The password to unlock the Directory Server private key
type: str
required: no
http_cert_files:
description:
File containing the Apache Server SSL certificate and private key
type: list
elements: str
required: no
http_cert_name:
description: Name of the Apache Server SSL certificate to install
type: str
required: no
http_pin:
description: The password to unlock the Apache Server private key
type: str
required: no
pkinit_cert_files:
description:
File containing the Kerberos KDC SSL certificate and private key
type: list
elements: str
required: no
pkinit_cert_name:
description: Name of the Kerberos KDC SSL certificate to install
type: str
required: no
pkinit_pin:
description: The password to unlock the Kerberos KDC private key
type: str
required: no
keytab:
description: Path to backed up keytab from previous enrollment
type: str
required: no
mkhomedir:
description: Create home directories for users on their first login
type: bool
required: no
force_join:
description: Force client enrollment even if already enrolled
type: bool
required: no
no_ntp:
description: Do not configure ntp
type: bool
required: no
ssh_trust_dns:
description: Configure OpenSSH client to trust DNS SSHFP records
type: bool
required: no
no_ssh:
description: Do not configure OpenSSH client
type: bool
required: no
no_sshd:
description: Do not configure OpenSSH server
type: bool
required: no
no_dns_sshfp:
description: Do not automatically create DNS SSHFP records
type: bool
required: no
allow_zone_overlap:
description: Create DNS zone even if it already exists
type: bool
default: no
required: no
reverse_zones:
description: The reverse DNS zones to use
type: list
elements: str
required: no
no_reverse:
description: Do not create new reverse DNS zone
type: bool
default: no
required: no
auto_reverse:
description: Create necessary reverse zones
type: bool
default: no
required: no
forwarders:
description: Add DNS forwarders
type: list
elements: str
required: no
no_forwarders:
description: Do not add any DNS forwarders, use root servers instead
type: bool
default: no
required: no
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
type: bool
default: no
required: no
forward_policy:
description: DNS forwarding policy for global forwarders
type: str
choices: ['first', 'only']
required: no
no_dnssec_validation:
description: Disable DNSSEC validation
type: bool
default: no
required: no
enable_compat:
description: Enable support for trusted domains for old clients
type: bool
default: no
required: no
netbios_name:
description: NetBIOS name of the IPA domain
type: str
required: no
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
type: int
default: 1000
required: no
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
type: int
default: 100000000
required: no
server:
description: Fully qualified name of IPA server to enroll to
type: str
required: yes
skip_conncheck:
description: Skip connection check to remote master
type: bool
required: no
sid_generation_always:
description: Enable SID generation always
type: bool
default: no
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
import tempfile
import traceback
from shutil import copyfile
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, options, installer, DN, paths, sysrestore,
ansible_module_get_parsed_ip_addresses, Env, ipautil, ipaldap,
installutils, ReplicaConfig, load_pkcs12, kinit_keytab, create_api,
rpc_client, check_remote_version, parse_version, check_remote_fips_mode,
ReplicationManager, promotion_check_ipa_domain, current_domain_level,
check_domain_level_is_supported, errors, ScriptError, setup_logging,
logger, check_dns_resolution, service, find_providing_server, ca, kra,
dns, no_matching_interface_for_ip_address_warning, adtrust,
constants, api, redirect_stdout, replica_conn_check, tasks
)
from ansible.module_utils import six
if six.PY3:
unicode = str
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=False, type='str', no_log=True),
password=dict(required=False, type='str', no_log=True),
ip_addresses=dict(required=False, type='list', elements='str',
default=[]),
domain=dict(required=False, type='str'),
realm=dict(required=False, type='str'),
hostname=dict(required=False, type='str'),
principal=dict(required=True, type='str'),
ca_cert_files=dict(required=False, type='list', elements='str',
default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
# server
setup_adtrust=dict(required=False, type='bool'),
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
setup_dns=dict(required=False, type='bool'),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', elements='str',
default=[]),
dirsrv_cert_name=dict(required=False, type='str'),
dirsrv_pin=dict(required=False, type='str'),
http_cert_files=dict(required=False, type='list', elements='str',
default=[]),
http_cert_name=dict(required=False, type='str'),
http_pin=dict(required=False, type='str'),
pkinit_cert_files=dict(required=False, type='list', elements='str',
default=[]),
pkinit_cert_name=dict(required=False, type='str'),
pkinit_pin=dict(required=False, type='str'),
# client
keytab=dict(required=False, type='str', no_log=False),
mkhomedir=dict(required=False, type='bool'),
force_join=dict(required=False, type='bool'),
no_ntp=dict(required=False, type='bool'),
ssh_trust_dns=dict(required=False, type='bool'),
no_ssh=dict(required=False, type='bool'),
no_sshd=dict(required=False, type='bool'),
no_dns_sshfp=dict(required=False, type='bool'),
# certificate system
# subject_base=dict(required=False),
# dns
allow_zone_overlap=dict(required=False, type='bool',
default=False),
reverse_zones=dict(required=False, type='list', elements='str',
default=[]),
no_reverse=dict(required=False, type='bool', default=False),
auto_reverse=dict(required=False, type='bool', default=False),
forwarders=dict(required=False, type='list', elements='str',
default=[]),
no_forwarders=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
forward_policy=dict(required=False, type='str',
choices=['first', 'only'], default=None),
no_dnssec_validation=dict(required=False, type='bool',
default=False),
# ad trust
enable_compat=dict(required=False, type='bool', default=False),
netbios_name=dict(required=False, type='str'),
rid_base=dict(required=False, type='int', default=1000),
secondary_rid_base=dict(required=False, type='int',
default=100000000),
# additional
server=dict(required=True, type='str'),
skip_conncheck=dict(required=False, type='bool'),
sid_generation_always=dict(required=False, type='bool',
default=False),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options.dm_password = ansible_module.params.get('dm_password')
options.password = options.dm_password
options.admin_password = ansible_module.params.get('password')
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
options.principal = ansible_module.params.get('principal')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.no_host_dns = ansible_module.params.get('no_host_dns')
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
options.dirsrv_cert_name = ansible_module.params.get('dirsrv_cert_name')
options.dirsrv_pin = ansible_module.params.get('dirsrv_pin')
options.http_cert_files = ansible_module.params.get('http_cert_files')
options.http_cert_name = ansible_module.params.get('http_cert_name')
options.http_pin = ansible_module.params.get('http_pin')
options.pkinit_cert_files = ansible_module.params.get('pkinit_cert_files')
options.pkinit_cert_name = ansible_module.params.get('pkinit_cert_name')
options.pkinit_pin = ansible_module.params.get('pkinit_pin')
# client
options.keytab = ansible_module.params.get('keytab')
options.mkhomedir = ansible_module.params.get('mkhomedir')
options.force_join = ansible_module.params.get('force_join')
options.no_ntp = ansible_module.params.get('no_ntp')
options.ssh_trust_dns = ansible_module.params.get('ssh_trust_dns')
options.no_ssh = ansible_module.params.get('no_ssh')
options.no_sshd = ansible_module.params.get('no_sshd')
options.no_dns_sshfp = ansible_module.params.get('no_dns_sshfp')
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
# options.subject_base = ansible_module.params.get('subject_base')
# options.ca_subject = ansible_module.params.get('ca_subject')
# dns
options.allow_zone_overlap = ansible_module.params.get(
'allow_zone_overlap')
options.reverse_zones = ansible_module.params.get('reverse_zones')
options.no_reverse = ansible_module.params.get('no_reverse')
options.auto_reverse = ansible_module.params.get('auto_reverse')
options.forwarders = ansible_module.params.get('forwarders')
options.no_forwarders = ansible_module.params.get('no_forwarders')
options.auto_forwarders = ansible_module.params.get('auto_forwarders')
options.forward_policy = ansible_module.params.get('forward_policy')
options.no_dnssec_validation = ansible_module.params.get(
'no_dnssec_validation')
# ad trust
options.enable_compat = ansible_module.params.get('enable_compat')
options.netbios_name = ansible_module.params.get('netbios_name')
options.rid_base = ansible_module.params.get('rid_base')
options.secondary_rid_base = ansible_module.params.get(
'secondary_rid_base')
# additional
# options._host_name_overridden = ansible_module.params.get(
# '_hostname_overridden')
options.server = ansible_module.params.get('server')
options.skip_conncheck = ansible_module.params.get('skip_conncheck')
sid_generation_always = ansible_module.params.get('sid_generation_always')
# random serial numbers are master_only, therefore setting to False
options.random_serial_numbers = False
# options._random_serial_numbers is generated by ca.install_check and
# later used by ca.install in the _setup_ca module.
options._random_serial_numbers = False
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
# prepare (install prepare, install checks) #
##########################################################################
# replica promote_check ##################################################
##########################################################################
ansible_log.debug("== PROMOTE CHECK ==")
# ansible_log.debug("-- NO_NTP --") # already done in test
# check selinux status, http and DS ports, NTP conflicting services
# common_check(options.no_ntp)
installer._enrollment_performed = False
installer._top_dir = tempfile.mkdtemp("ipa")
# with ipautil.private_ccache():
dir_path = tempfile.mkdtemp(prefix='krbcc')
os.environ['KRB5CCNAME'] = os.path.join(dir_path, 'ccache')
ansible_log.debug("-- API --")
env = Env()
env._bootstrap(context='installer', confdir=paths.ETC_IPA, log=None)
env._finalize_core(**dict(constants.DEFAULT_CONFIG))
# pylint: disable=no-member
xmlrpc_uri = 'https://{0}/ipa/xml'.format(ipautil.format_netloc(env.host))
if hasattr(ipaldap, "realm_to_ldapi_uri"):
realm_to_ldapi_uri = ipaldap.realm_to_ldapi_uri
else:
realm_to_ldapi_uri = installutils.realm_to_ldapi_uri
api.bootstrap(in_server=True,
context='installer',
confdir=paths.ETC_IPA,
ldap_uri=realm_to_ldapi_uri(env.realm),
xmlrpc_uri=xmlrpc_uri)
# pylint: enable=no-member
api.finalize()
ansible_log.debug("-- REPLICA_CONFIG --")
config = ReplicaConfig()
config.realm_name = api.env.realm
config.host_name = api.env.host
config.domain_name = api.env.domain
config.master_host_name = api.env.server
if not api.env.ca_host or api.env.ca_host == api.env.host:
# ca_host has not been configured explicitly, prefer source master
config.ca_host_name = api.env.server
else:
# default to ca_host from IPA config
config.ca_host_name = api.env.ca_host
config.kra_host_name = config.ca_host_name
config.ca_ds_port = 389
config.setup_ca = options.setup_ca
config.setup_kra = options.setup_kra
config.dir = installer._top_dir
config.basedn = api.env.basedn
# config.hidden_replica = options.hidden_replica
# load and check certificates #
ansible_log.debug("-- CERT_FILES --")
http_pkcs12_file = None
http_pkcs12_info = None
http_ca_cert = None
dirsrv_pkcs12_file = None
dirsrv_pkcs12_info = None
dirsrv_ca_cert = None
pkinit_pkcs12_file = None
pkinit_pkcs12_info = None
pkinit_ca_cert = None
if options.http_cert_files:
ansible_log.debug("-- HTTP_CERT_FILES --")
if options.http_pin is None:
ansible_module.fail_json(
msg="Apache Server private key unlock password required")
http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12(
cert_files=options.http_cert_files,
key_password=options.http_pin,
key_nickname=options.http_cert_name,
ca_cert_files=options.ca_cert_files,
host_name=config.host_name)
http_pkcs12_info = (http_pkcs12_file.name, http_pin)
if options.dirsrv_cert_files:
ansible_log.debug("-- DIRSRV_CERT_FILES --")
if options.dirsrv_pin is None:
ansible_module.fail_json(
msg="Directory Server private key unlock password required")
dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12(
cert_files=options.dirsrv_cert_files,
key_password=options.dirsrv_pin,
key_nickname=options.dirsrv_cert_name,
ca_cert_files=options.ca_cert_files,
host_name=config.host_name)
dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin)
if options.pkinit_cert_files:
ansible_log.debug("-- PKINIT_CERT_FILES --")
if options.pkinit_pin is None:
ansible_module.fail_json(
msg="Kerberos KDC private key unlock password required")
pkinit_pkcs12_file, pkinit_pin, pkinit_ca_cert = load_pkcs12(
cert_files=options.pkinit_cert_files,
key_password=options.pkinit_pin,
key_nickname=options.pkinit_cert_name,
ca_cert_files=options.ca_cert_files,
realm_name=config.realm_name)
pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin)
if (options.http_cert_files and options.dirsrv_cert_files and
http_ca_cert != dirsrv_ca_cert):
ansible_module.fail_json(
msg="Apache Server SSL certificate and Directory "
"Server SSL certificate are not signed by the same"
" CA certificate")
if (options.http_cert_files and
options.pkinit_cert_files and
http_ca_cert != pkinit_ca_cert):
ansible_module.fail_json(
msg="Apache Server SSL certificate and PKINIT KDC "
"certificate are not signed by the same CA "
"certificate")
# Copy pkcs12_files to make them persistent till deployment is done
# and encode certificates for ansible compatibility
if http_pkcs12_info is not None:
copyfile(http_pkcs12_file.name, "/etc/ipa/.tmp_pkcs12_http")
http_pkcs12_info = ("/etc/ipa/.tmp_pkcs12_http", http_pin)
http_ca_cert = ""
if dirsrv_pkcs12_info is not None:
copyfile(dirsrv_pkcs12_file.name, "/etc/ipa/.tmp_pkcs12_dirsrv")
dirsrv_pkcs12_info = ("/etc/ipa/.tmp_pkcs12_dirsrv", dirsrv_pin)
dirsrv_ca_cert = ""
if pkinit_pkcs12_info is not None:
copyfile(pkinit_pkcs12_file.name, "/etc/ipa/.tmp_pkcs12_pkinit")
pkinit_pkcs12_info = ("/etc/ipa/.tmp_pkcs12_pkinit", pkinit_pin)
pkinit_ca_cert = ""
ansible_log.debug("-- FQDN --")
installutils.verify_fqdn(config.host_name, options.no_host_dns)
installutils.verify_fqdn(config.master_host_name, options.no_host_dns)
ansible_log.debug("-- KINIT_KEYTAB --")
ccache = os.environ['KRB5CCNAME']
kinit_keytab('host/{env.host}@{env.realm}'.format(env=api.env),
paths.KRB5_KEYTAB,
ccache)
ansible_log.debug("-- CA_CRT --")
cafile = paths.IPA_CA_CRT
if not os.path.isfile(cafile):
ansible_module.fail_json(
msg="CA cert file is not available! Please reinstall"
"the client and try again.")
ansible_log.debug("-- REMOTE_API --")
ldapuri = 'ldaps://%s' % ipautil.format_netloc(config.master_host_name)
xmlrpc_uri = 'https://{0}/ipa/xml'.format(
ipautil.format_netloc(config.master_host_name))
remote_api = create_api(mode=None)
remote_api.bootstrap(in_server=True,
context='installer',
confdir=paths.ETC_IPA,
ldap_uri=ldapuri,
xmlrpc_uri=xmlrpc_uri)
remote_api.finalize()
installer._remote_api = remote_api
ansible_log.debug("-- RPC_CLIENT --")
with rpc_client(remote_api) as client:
check_remote_version(client, parse_version(api.env.version))
check_remote_fips_mode(client, api.env.fips_mode)
conn = remote_api.Backend.ldap2
replman = None
try:
ansible_log.debug("-- CONNECT --")
# Try out authentication
conn.connect(ccache=ccache)
replman = ReplicationManager(config.realm_name,
config.master_host_name, None)
ansible_log.debug("-- CHECK IPA_DOMAIN --")
promotion_check_ipa_domain(conn, remote_api.env.basedn)
ansible_log.debug("-- CHECK DOMAIN_LEVEL --")
# Make sure that domain fulfills minimal domain level
# requirement
domain_level = current_domain_level(remote_api)
check_domain_level_is_supported(domain_level)
if domain_level < constants.MIN_DOMAIN_LEVEL:
ansible_module.fail_json(
msg="Cannot promote this client to a replica. The domain "
"level "
"must be raised to {mindomainlevel} before the replica can be "
"installed".format(
mindomainlevel=constants.MIN_DOMAIN_LEVEL))
ansible_log.debug("-- CHECK AUTHORIZATION --")
# Check authorization
result = remote_api.Command['hostgroup_find'](
cn=u'ipaservers',
host=[unicode(api.env.host)]
)['result']
add_to_ipaservers = not result
ansible_log.debug("-- ADD_TO_IPASERVERS --")
if add_to_ipaservers:
if options.password and not options.admin_password:
raise errors.ACIError(info="Not authorized")
if installer._ccache is None:
os.environ.pop('KRB5CCNAME', None)
else:
os.environ['KRB5CCNAME'] = installer._ccache
try:
installutils.check_creds(options, config.realm_name)
installer._ccache = os.environ.get('KRB5CCNAME')
finally:
os.environ['KRB5CCNAME'] = ccache
conn.disconnect()
conn.connect(ccache=installer._ccache)
try:
result = remote_api.Command['hostgroup_show'](
u'ipaservers',
all=True,
rights=True
)['result']
if 'w' not in result['attributelevelrights']['member']:
raise errors.ACIError(info="Not authorized")
finally:
ansible_log.debug("-- RECONNECT --")
conn.disconnect()
conn.connect(ccache=ccache)
ansible_log.debug("-- CHECK FOR REPLICATION AGREEMENT --")
# Check that we don't already have a replication agreement
if replman.get_replication_agreement(config.host_name):
msg = ("A replication agreement for this host already exists. "
"It needs to be removed.\n"
"Run this command:\n"
" %% ipa-replica-manage del {host} --force"
.format(host=config.host_name))
raise ScriptError(msg, rval=3)
ansible_log.debug("-- DETECT REPLICATION MANAGER GROUP --")
# Detect if the other master can handle replication managers
# cn=replication managers,cn=sysaccounts,cn=etc,$SUFFIX
dn = DN(('cn', 'replication managers'), ('cn', 'sysaccounts'),
('cn', 'etc'), ipautil.realm_to_suffix(config.realm_name))
try:
conn.get_entry(dn)
except errors.NotFound:
msg = ("The Replication Managers group is not available in "
"the domain. Replica promotion requires the use of "
"Replication Managers to be able to replicate data. "
"Upgrade the peer master or use the ipa-replica-prepare "
"command on the master and use a prep file to install "
"this replica.")
logger.error("%s", msg)
raise ScriptError(msg, rval=3)
ansible_log.debug("-- CHECK DNS_MASTERS --")
dns_masters = remote_api.Object['dnsrecord'].get_dns_masters()
if dns_masters:
if not options.no_host_dns:
logger.debug('Check forward/reverse DNS resolution')
resolution_ok = (
check_dns_resolution(config.master_host_name,
dns_masters) and
check_dns_resolution(config.host_name, dns_masters))
if not resolution_ok and installer.interactive:
if not ipautil.user_input("Continue?", False):
raise ScriptError(rval=0)
else:
logger.debug('No IPA DNS servers, '
'skipping forward/reverse resolution check')
ansible_log.debug("-- GET_IPA_CONFIG --")
entry_attrs = conn.get_ipa_config()
subject_base = entry_attrs.get('ipacertificatesubjectbase', [None])[0]
if subject_base is not None:
config.subject_base = DN(subject_base)
ansible_log.debug("-- SEARCH FOR CA --")
# Find if any server has a CA
if not hasattr(service, "find_providing_server"):
_host = [config.ca_host_name]
else:
_host = config.ca_host_name
ca_host = find_providing_server('CA', conn, _host)
if ca_host is not None:
config.ca_host_name = ca_host
ca_enabled = True
if options.dirsrv_cert_files:
msg = ("Certificates could not be provided when "
"CA is present on some master.")
logger.error(msg)
raise ScriptError(msg, rval=3)
else:
if options.setup_ca:
msg = ("The remote master does not have a CA "
"installed, can't set up CA")
logger.error(msg)
raise ScriptError(msg, rval=3)
ca_enabled = False
if not options.dirsrv_cert_files:
msg = ("Cannot issue certificates: a CA is not "
"installed. Use the --http-cert-file, "
"--dirsrv-cert-file options to provide "
"custom certificates.")
logger.error(msg)
raise ScriptError(msg, rval=3)
ansible_log.debug("-- SEARCH FOR KRA --")
if not hasattr(service, "find_providing_server"):
_host = [config.kra_host_name]
else:
_host = config.kra_host_name
kra_host = find_providing_server('KRA', conn, _host)
if kra_host is not None:
config.kra_host_name = kra_host
kra_enabled = True
else:
if options.setup_kra:
msg = ("There is no active KRA server in the domain, "
"can't setup a KRA clone")
logger.error(msg)
raise ScriptError(msg, rval=3)
kra_enabled = False
ansible_log.debug("-- CHECK CA --")
if ca_enabled:
options.realm_name = config.realm_name
options.host_name = config.host_name
ca.install_check(False, config, options)
ansible_log.debug(" ca.external_cert_file=%s" %
repr(ca.external_cert_file))
ansible_log.debug(" ca.external_ca_file=%s" %
repr(ca.external_ca_file))
# TODO
# TODO
# Save global vars external_cert_file, external_ca_file for
# later use
# TODO
# TODO
ansible_log.debug("-- CHECK KRA --")
if kra_enabled:
try:
kra.install_check(remote_api, config, options)
except RuntimeError as e:
raise ScriptError(e)
ansible_log.debug("-- CHECK DNS --")
if options.setup_dns:
dns.install_check(False, remote_api, True, options,
config.host_name)
config.ips = dns.ip_addresses
else:
config.ips = installutils.get_server_ip_address(
config.host_name, not installer.interactive,
False, options.ip_addresses)
# check addresses here, dns module is doing own check
no_matching_interface_for_ip_address_warning(config.ips)
ansible_log.debug("-- CHECK ADTRUST --")
if options.setup_adtrust or sid_generation_always:
adtrust.install_check(False, options, remote_api)
except errors.ACIError:
logger.debug("%s", traceback.format_exc())
ansible_module.fail_json(
msg=("\nInsufficient privileges to promote the server."
"\nPossible issues:"
"\n- A user has insufficient privileges"
"\n- This client has insufficient privileges "
"to become an IPA replica"))
except errors.LDAPError:
logger.debug("%s", traceback.format_exc())
ansible_module.fail_json(msg="\nUnable to connect to LDAP server %s" %
config.master_host_name)
except ScriptError as e:
ansible_module.fail_json(msg=str(e))
finally:
if replman and replman.conn:
ansible_log.debug("-- UNBIND REPLMAN--")
replman.conn.unbind()
if conn.isconnected():
ansible_log.debug("-- DISCONNECT --")
conn.disconnect()
ansible_log.debug("-- CHECK CONNECTION --")
# check connection
if not options.skip_conncheck:
if add_to_ipaservers:
# use user's credentials when the server host is not ipaservers
if installer._ccache is None:
os.environ.pop('KRB5CCNAME', None)
else:
os.environ['KRB5CCNAME'] = installer._ccache
try:
with redirect_stdout(ansible_log):
replica_conn_check(
config.master_host_name, config.host_name,
config.realm_name, options.setup_ca, 389,
options.admin_password, principal=options.principal,
ca_cert_file=cafile)
except ScriptError as e:
ansible_module.fail_json(msg=str(e))
finally:
if add_to_ipaservers:
os.environ['KRB5CCNAME'] = ccache
if hasattr(tasks, "configure_pkcs11_modules"):
if tasks.configure_pkcs11_modules(fstore):
ansible_log.info("Disabled p11-kit-proxy")
installer._ca_enabled = ca_enabled
installer._kra_enabled = kra_enabled
installer._ca_file = cafile
installer._fstore = fstore
installer._sstore = sstore
installer._config = config
installer._add_to_ipaservers = add_to_ipaservers
# done #
ansible_module.exit_json(
changed=True,
ccache=ccache,
installer_ccache=installer._ccache,
subject_base=str(config.subject_base),
forward_policy=options.forward_policy,
_ca_enabled=ca_enabled,
_ca_subject=str(options._ca_subject),
_subject_base=str(options._subject_base) if options._subject_base
is not None else None,
_kra_enabled=kra_enabled,
_ca_file=cafile,
_top_dir=installer._top_dir,
_add_to_ipaservers=add_to_ipaservers,
_dirsrv_pkcs12_info=dirsrv_pkcs12_info,
_dirsrv_ca_cert=dirsrv_ca_cert,
_http_pkcs12_info=http_pkcs12_info,
_http_ca_cert=http_ca_cert,
_pkinit_pkcs12_info=pkinit_pkcs12_info,
_pkinit_ca_cert=pkinit_ca_cert,
_random_serial_numbers=options._random_serial_numbers,
no_dnssec_validation=options.no_dnssec_validation,
config_setup_ca=config.setup_ca,
config_master_host_name=config.master_host_name,
config_ca_host_name=config.ca_host_name,
config_kra_host_name=config.kra_host_name,
config_ips=[str(ip) for ip in config.ips],
# ad trust
dns_ip_addresses=[str(ip) for ip in dns.ip_addresses],
dns_reverse_zones=dns.reverse_zones,
rid_base=options.rid_base,
secondary_rid_base=options.secondary_rid_base,
adtrust_netbios_name=adtrust.netbios_name,
adtrust_reset_netbios_name=adtrust.reset_netbios_name)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_promote_openldap_conf.py 0000664 0000000 0000000 00000010557 14600563364 0031434 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_promote_openldap_conf
short_description: Promote openldap.conf
description:
Promote openldap.conf
options:
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
config_setup_ca:
description: The config setup_ca setting
type: bool
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, redirect_stdout, promote_openldap_conf
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_kra=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
ccache=dict(required=True, type='str'),
_top_dir=dict(required=True, type='str'),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True, type='str'),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# server
options.setup_kra = ansible_module.params.get('setup_kra')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._top_dir = ansible_module.params.get('_top_dir')
config_setup_ca = ansible_module.params.get('config_setup_ca')
installer.setup_ca = config_setup_ca
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
# init #
ansible_log.debug("== INSTALL ==")
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.subject_base = options.subject_base
config.setup_ca = config_setup_ca
config.master_host_name = config_master_host_name
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
ccache = os.environ['KRB5CCNAME']
with redirect_stdout(ansible_log):
ansible_log.debug("-- PROMOTE OPENLDAP_CONF--")
promote_openldap_conf(config.host_name, config.master_host_name)
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_promote_sssd.py 0000664 0000000 0000000 00000010441 14600563364 0027571 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_promote_sssd
short_description: Promote sssd
description:
Promote sssd
options:
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
config_setup_ca:
description: The config setup_ca setting
type: bool
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, redirect_stdout, promote_sssd
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_kra=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
ccache=dict(required=True, type='str'),
_top_dir=dict(required=True, type='str'),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True, type='str'),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# server
options.setup_kra = ansible_module.params.get('setup_kra')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._top_dir = ansible_module.params.get('_top_dir')
config_setup_ca = ansible_module.params.get('config_setup_ca')
installer.setup_ca = config_setup_ca
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
# init #
ansible_log.debug("== INSTALL ==")
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.subject_base = options.subject_base
config.setup_ca = config_setup_ca
config.master_host_name = config_master_host_name
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
ccache = os.environ['KRB5CCNAME']
with redirect_stdout(ansible_log):
ansible_log.debug("-- PROMOTE SSSD --")
promote_sssd(config.host_name)
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_restart_kdc.py 0000664 0000000 0000000 00000012617 14600563364 0027364 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_restart_kdc
short_description: Restart KDC
description:
Restart KDC
options:
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
required: no
no_ui_redirect:
description: Do not automatically redirect to the Web UI
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_ca_file:
description: The installer _ca_file setting
type: str
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports,
AnsibleModuleLog, setup_logging, installer, DN, paths, sysrestore,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, service,
krbinstance
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
config_master_host_name=dict(required=True, type='str'),
ccache=dict(required=True, type='str'),
_ca_file=dict(required=False, type='str'),
_top_dir=dict(required=True, type='str'),
dirman_password=dict(required=True, type='str', no_log=True),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.dirman_password = dirman_password
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
api.Backend.ldap2.connect()
conn.connect(ccache=ccache)
# krb
krb = krbinstance.KrbInstance(fstore)
krb.set_output(ansible_log)
with redirect_stdout(ansible_log):
krb.init_info(api.env.realm, api.env.host,
setup_pkinit=not options.no_pkinit,
subject_base=options.subject_base)
ansible_log.debug("-- RESTART KDC --")
service.print_msg("Restarting the KDC")
krb.restart()
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_setup_adtrust.py 0000664 0000000 0000000 00000013622 14600563364 0027762 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_setup_adtrust
short_description: Setup adtrust
description:
Setup adtrust
options:
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
enable_compat:
description: Enable support for trusted domains for old clients
type: bool
default: no
required: no
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
type: int
required: no
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
type: int
required: no
adtrust_netbios_name:
description: The adtrust netbios_name setting
type: str
required: yes
adtrust_reset_netbios_name:
description: The adtrust reset_netbios_name setting
type: bool
required: yes
ccache:
description: The local ccache
type: str
required: yes
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
setup_ca:
description: Configure a dogtag CA
type: bool
required: yes
setup_adtrust:
description: Configure AD trust capability
type: bool
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, setup_logging, installer, DN, paths, sysrestore,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, adtrust,
check_imports
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_kra=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# ad trust
enable_compat=dict(required=False, type='bool', default=False),
rid_base=dict(required=False, type='int'),
secondary_rid_base=dict(required=False, type='int'),
# additional
adtrust_netbios_name=dict(required=True, type='str'),
adtrust_reset_netbios_name=dict(required=True, type='bool'),
# additional
ccache=dict(required=True, type='str'),
_top_dir=dict(required=True, type='str'),
setup_ca=dict(required=True, type='bool'),
setup_adtrust=dict(required=True, type='bool'),
config_master_host_name=dict(required=True, type='str'),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# server
options.setup_kra = ansible_module.params.get('setup_kra')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# ad trust
options.enable_compat = ansible_module.params.get('enable_compat')
options.rid_base = ansible_module.params.get('rid_base')
options.secondary_rid_base = ansible_module.params.get(
'secondary_rid_base')
# additional
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._top_dir = ansible_module.params.get('_top_dir')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
adtrust.netbios_name = ansible_module.params.get('adtrust_netbios_name')
adtrust.reset_netbios_name = ansible_module.params.get(
'adtrust_reset_netbios_name')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.subject_base = options.subject_base
config.master_host_name = config_master_host_name
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
ccache = os.environ['KRB5CCNAME']
api.Backend.ldap2.connect()
with redirect_stdout(ansible_log):
ansible_log.debug("-- INSTALL ADTRUST --")
adtrust.install(False, options, fstore, api)
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_setup_ca.py 0000664 0000000 0000000 00000022666 14600563364 0026667 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_setup_ca
short_description: Setup CA
description:
Setup CA
options:
pki_config_override:
description: Path to ini file with config overrides
type: str
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_ca_enabled:
description: The installer _ca_enabled setting
type: bool
required: no
_ca_file:
description: The installer _ca_file setting
type: str
required: no
_kra_enabled:
description: The installer _kra_enabled setting
type: bool
required: no
_kra_host_name:
description: The installer _kra_host_name setting
type: str
required: no
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
type: list
elements: str
required: no
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
type: list
elements: str
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
_ca_subject:
description: The installer _ca_subject setting
type: str
required: yes
_subject_base:
description: The installer _subject_base setting
type: str
required: yes
_random_serial_numbers:
description: The installer _random_serial_numbers setting
type: bool
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
config_setup_ca:
description: The config setup_ca setting
type: bool
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
config_ca_host_name:
description: The config ca_host_name setting
type: str
required: yes
config_ips:
description: The config ips setting
type: list
elements: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
ansible_module_get_parsed_ip_addresses,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, ca,
custodiainstance
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
pki_config_override=dict(required=False, type='str'),
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
ccache=dict(required=True, type='str'),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False, type='str'),
_kra_enabled=dict(required=False, type='bool'),
_kra_host_name=dict(required=False, type='str'),
_dirsrv_pkcs12_info=dict(required=False, type='list',
elements='str'),
_pkinit_pkcs12_info=dict(required=False, type='list',
elements='str'),
_top_dir=dict(required=True, type='str'),
_ca_subject=dict(required=True, type='str'),
_subject_base=dict(required=True, type='str'),
_random_serial_numbers=dict(required=True, type='bool'),
dirman_password=dict(required=True, type='str', no_log=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True, type='str'),
config_ca_host_name=dict(required=True, type='str'),
config_ips=dict(required=False, type='list', elements='str',
default=[]),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# basic
options.pki_config_override = ansible_module.params.get(
'pki_config_override')
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
kra_enabled = ansible_module.params.get('_kra_enabled')
kra_host_name = ansible_module.params.get('_kra_host_name')
installer._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
installer._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
options._ca_subject = ansible_module.params.get('_ca_subject')
if options._ca_subject is not None:
options._ca_subject = DN(options._ca_subject)
options._subject_base = ansible_module.params.get('_subject_base')
if options._subject_base is not None:
options._subject_base = DN(options._subject_base)
options._random_serial_numbers = ansible_module.params.get(
'_random_serial_numbers')
dirman_password = ansible_module.params.get('dirman_password')
config_setup_ca = ansible_module.params.get('config_setup_ca')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
config_ca_host_name = ansible_module.params.get('config_ca_host_name')
config_ips = ansible_module_get_parsed_ip_addresses(ansible_module,
"config_ips")
# init #
ansible_log.debug("== INSTALL ==")
options = installer
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.dirman_password = dirman_password
config.setup_ca = config_setup_ca
config.master_host_name = config_master_host_name
config.ca_host_name = config_ca_host_name
config.ips = config_ips
config.promote = options.promote
config.kra_enabled = kra_enabled
config.kra_host_name = kra_host_name
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
options._remote_api = remote_api
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
api.Backend.ldap2.connect()
# conn.connect(ccache=ccache)
ansible_log.debug("-- INSTALL CA --")
with redirect_stdout(ansible_log):
options.realm_name = config.realm_name
options.domain_name = config.domain_name
options.host_name = config.host_name
options.dm_password = config.dirman_password
if not hasattr(custodiainstance, "get_custodia_instance"):
ca.install(False, config, options)
else:
if kra_enabled:
# A KRA peer always provides a CA, too.
mode = custodiainstance.CustodiaModes.KRA_PEER
elif ca_enabled:
mode = custodiainstance.CustodiaModes.CA_PEER
else:
mode = custodiainstance.CustodiaModes.MASTER_PEER
custodia = custodiainstance.get_custodia_instance(config, mode)
ca.install(False, config, options, custodia=custodia)
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_setup_certmonger.py 0000664 0000000 0000000 00000003761 14600563364 0030444 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_setup_certmonger
short_description: Setup certmonger
description:
Setup certmonger
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports,
AnsibleModuleLog, setup_logging, redirect_stdout, configure_certmonger
)
def main():
ansible_module = AnsibleModule(
argument_spec={},
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
with redirect_stdout(ansible_log):
ansible_log.debug("-- CONFIGURE_CERTMONGER --")
# FIXME: allow to use passed in certs instead
configure_certmonger()
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_setup_custodia.py 0000664 0000000 0000000 00000016535 14600563364 0030115 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_setup_custodia
short_description: Setup custodia
description:
Setup custodia
options:
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
required: no
no_ui_redirect:
description: Do not automatically redirect to the Web UI
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_ca_enabled:
description: The installer _ca_enabled setting
type: bool
required: no
_ca_file:
description: The installer _ca_file setting
type: str
required: no
_kra_enabled:
description: The installer _kra_enabled setting
type: bool
required: no
_kra_host_name:
description: The installer _kra_host_name setting
type: str
required: no
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
type: list
elements: str
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, custodiainstance
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
config_master_host_name=dict(required=True, type='str'),
ccache=dict(required=True, type='str'),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False, type='str'),
_kra_enabled=dict(required=False, type='bool'),
_kra_host_name=dict(required=False, type='str'),
_pkinit_pkcs12_info=dict(required=False, type='list',
elements='str'),
_top_dir=dict(required=True, type='str'),
dirman_password=dict(required=True, type='str', no_log=True),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
kra_enabled = ansible_module.params.get('_kra_enabled')
kra_host_name = ansible_module.params.get('_kra_host_name')
options._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
# init #
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.dirman_password = dirman_password
config.promote = installer.promote
config.kra_enabled = kra_enabled
config.kra_host_name = kra_host_name
config.setup_ca = options.setup_ca
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
api.Backend.ldap2.connect()
conn.connect(ccache=ccache)
with redirect_stdout(ansible_log):
ansible_log.debug("-- INSTALL_CUSTODIA --")
if not hasattr(custodiainstance, "get_custodia_instance"):
custodia = custodiainstance.CustodiaInstance(config.host_name,
config.realm_name)
if promote and \
hasattr(custodiainstance.CustodiaInstance, "create_replica"):
ansible_log.debug("-- CUSTODIA CREATE_REPLICA --")
custodia.create_replica(config.master_host_name)
else:
ansible_log.debug("-- CUSTODIA CREATE_INSTANCE --")
custodia.create_instance()
else:
if kra_enabled:
# A KRA peer always provides a CA, too.
mode = custodiainstance.CustodiaModes.KRA_PEER
elif ca_enabled:
mode = custodiainstance.CustodiaModes.CA_PEER
else:
mode = custodiainstance.CustodiaModes.MASTER_PEER
custodia = custodiainstance.get_custodia_instance(config, mode)
custodia.create_instance()
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_setup_dns.py 0000664 0000000 0000000 00000014731 14600563364 0027062 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_setup_dns
short_description: Setup DNS
description:
Setup DNS
options:
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
setup_dns:
description: Configure bind with our zone
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
zonemgr:
description: DNS zone manager e-mail address. Defaults to hostmaster@DOMAIN
type: str
required: no
forwarders:
description: Add DNS forwarders
type: list
elements: str
required: no
forward_policy:
description: DNS forwarding policy for global forwarders
type: str
choices: ['first', 'only']
required: no
no_dnssec_validation:
description: Disable DNSSEC validation
type: bool
default: no
required: no
dns_ip_addresses:
description: The dns ip_addresses setting
type: list
elements: str
required: yes
dns_reverse_zones:
description: The dns reverse_zones setting
type: list
elements: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
setup_ca:
description: Configure a dogtag CA
type: bool
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, dns,
ansible_module_get_parsed_ip_addresses
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_kra=dict(required=False, type='bool'),
setup_dns=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# dns
zonemgr=dict(required=False, type='str'),
forwarders=dict(required=False, type='list', elements='str',
default=[]),
forward_policy=dict(required=False, type='str',
choices=['first', 'only'], default=None),
no_dnssec_validation=dict(required=False, type='bool',
default=False),
# additional
dns_ip_addresses=dict(required=True, type='list', elements='str'),
dns_reverse_zones=dict(required=True, type='list', elements='str'),
ccache=dict(required=True, type='str'),
_top_dir=dict(required=True, type='str'),
setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True, type='str'),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# server
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# dns
options.zonemgr = ansible_module.params.get('zonemgr')
options.forwarders = ansible_module.params.get('forwarders')
options.forward_policy = ansible_module.params.get('forward_policy')
options.no_dnssec_validation = ansible_module.params.get(
'no_dnssec_validation')
# additional
dns.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module, 'dns_ip_addresses')
dns.reverse_zones = ansible_module.params.get('dns_reverse_zones')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._top_dir = ansible_module.params.get('_top_dir')
options.setup_ca = ansible_module.params.get('setup_ca')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
# init #
ansible_log.debug("== INSTALL ==")
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.subject_base = options.subject_base
config.master_host_name = config_master_host_name
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
api.Backend.ldap2.connect()
with redirect_stdout(ansible_log):
if options.setup_dns:
ansible_log.debug("-- INSTALL DNS --")
dns.install(False, True, options, api)
else:
ansible_log.debug("-- DNS UPDATE_SYSTEM_RECORDS --")
api.Command.dns_update_system_records()
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_setup_ds.py 0000664 0000000 0000000 00000035012 14600563364 0026677 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_setup_ds
short_description: Setup DS
description:
Setup DS
options:
dm_password:
description: Directory Manager password
type: str
required: no
password:
description: Admin user kerberos password
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: no
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: no
hostname:
description: Fully qualified name of this host
type: str
required: no
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
type: list
elements: str
required: no
no_host_dns:
description: Do not use DNS for hostname lookup during installation
type: bool
default: no
required: no
setup_adtrust:
description: Configure AD trust capability
type: bool
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
setup_dns:
description: Configure bind with our zone
type: bool
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
default: no
required: no
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
type: str
required: no
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
type: list
elements: str
required: no
force_join:
description: Force client enrollment even if already enrolled
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
server:
description: Fully qualified name of IPA server to enroll to
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
installer_ccache:
description: The installer ccache setting
type: str
required: yes
_ca_enabled:
description: The installer _ca_enabled setting
type: bool
required: no
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
type: list
elements: str
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
_add_to_ipaservers:
description: The installer _add_to_ipaservers setting
type: bool
required: yes
_ca_subject:
description: The installer _ca_subject setting
type: str
required: yes
_subject_base:
description: The installer _subject_base setting
type: str
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
config_setup_ca:
description: The config setup_ca setting
type: bool
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
config_ca_host_name:
description: The config ca_host_name setting
type: str
required: yes
config_ips:
description: The config ips setting
type: list
elements: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
sysrestore, ansible_module_get_parsed_ip_addresses,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, redirect_stdout, ipaldap,
install_replica_ds, install_dns_records, ntpinstance, ScriptError,
getargspec
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=False, type='str', no_log=True),
password=dict(required=False, type='str', no_log=True),
ip_addresses=dict(required=False, type='list', elements='str',
default=[]),
domain=dict(required=False, type='str'),
realm=dict(required=False, type='str'),
hostname=dict(required=False, type='str'),
ca_cert_files=dict(required=False, type='list', elements='str',
default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
# server
setup_adtrust=dict(required=False, type='bool'),
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
setup_dns=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool', default=False),
dirsrv_config_file=dict(required=False, type='str'),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', elements='str',
default=[]),
# client
force_join=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
server=dict(required=True, type='str'),
ccache=dict(required=True, type='str'),
installer_ccache=dict(required=True, type='str'),
_ca_enabled=dict(required=False, type='bool'),
_dirsrv_pkcs12_info=dict(required=False, type='list',
elements='str'),
_top_dir=dict(required=True, type='str'),
_add_to_ipaservers=dict(required=True, type='bool'),
_ca_subject=dict(required=True, type='str'),
_subject_base=dict(required=True, type='str'),
dirman_password=dict(required=True, type='str', no_log=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True, type='str'),
config_ca_host_name=dict(required=True, type='str'),
config_ips=dict(required=False, type='list', elements='str',
default=[]),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
options.dm_password = ansible_module.params.get('dm_password')
options.password = options.dm_password
options.admin_password = ansible_module.params.get('password')
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.no_host_dns = ansible_module.params.get('no_host_dns')
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
# client
options.force_join = ansible_module.params.get('force_join')
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options.ca_subject = ansible_module.params.get('ca_subject')
# additional
# options._host_name_overridden = ansible_module.params.get(
# '_hostname_overridden')
options.server = ansible_module.params.get('server')
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info')
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options._top_dir = ansible_module.params.get('_top_dir')
options._add_to_ipaservers = ansible_module.params.get(
'_add_to_ipaservers')
options._ca_subject = ansible_module.params.get('_ca_subject')
options._subject_base = ansible_module.params.get('_subject_base')
dirman_password = ansible_module.params.get('dirman_password')
config_setup_ca = ansible_module.params.get('config_setup_ca')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
config_ca_host_name = ansible_module.params.get('config_ca_host_name')
config_ips = ansible_module_get_parsed_ip_addresses(ansible_module,
"config_ips")
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.subject_base = options.subject_base
config.dirman_password = dirman_password
config.setup_ca = config_setup_ca
config.master_host_name = config_master_host_name
config.ca_host_name = config_ca_host_name
config.ips = config_ips
config.promote = installer.promote
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
cafile = paths.IPA_CA_CRT
try:
ansible_log.debug("-- CONNECT --")
if promote:
conn.connect(ccache=ccache)
else:
# dmlvl 0 replica install should always use DM credentials
# to create remote LDAP connection. Since ACIs permitting hosts
# to manage their own services were added in 4.2 release,
# the master denies this operations.
conn.connect(bind_dn=ipaldap.DIRMAN_DN, cacert=cafile,
bind_pw=dirman_password)
ansible_log.debug("-- CONFIGURE DIRSRV --")
# Configure dirsrv
with redirect_stdout(ansible_log):
# pylint: disable=deprecated-method
argspec = getargspec(install_replica_ds)
# pylint: enable=deprecated-method
if "promote" in argspec.args:
ds = install_replica_ds(config, options, ca_enabled,
remote_api,
ca_file=cafile,
promote=promote,
pkcs12_info=dirsrv_pkcs12_info)
else:
if "fstore" in argspec.args:
ds = install_replica_ds(config, options, ca_enabled,
remote_api,
ca_file=cafile,
pkcs12_info=dirsrv_pkcs12_info,
fstore=fstore)
else:
ds = install_replica_ds(config, options, ca_enabled,
remote_api,
ca_file=cafile,
pkcs12_info=dirsrv_pkcs12_info)
# pylint: disable=deprecated-method
ansible_log.debug("-- INSTALL DNS RECORDS --")
# pylint: enable=deprecated-method
# Always try to install DNS records
# pylint: disable=deprecated-method
argspec = getargspec(install_dns_records)
# pylint: enable=deprecated-method
if "fstore" not in argspec.args:
install_dns_records(config, options, remote_api)
else:
install_dns_records(config, options, remote_api, fstore=fstore)
# TODO: check if ntp needs to be enabled later on
ansible_log.debug("-- NTP LDAP ENABLE --")
if ntpinstance is not None:
ntpinstance.ntp_ldap_enable(config.host_name, ds.suffix,
remote_api.env.realm)
except (ScriptError, RuntimeError) as e:
ansible_module.fail_json(msg=str(e))
finally:
if conn.isconnected():
ansible_log.debug("-- DISCONNECT --")
conn.disconnect()
# done #
ansible_module.exit_json(changed=True,
ds_suffix=str(ds.suffix),
ds_ca_subject=str(ds.ca_subject))
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_setup_http.py 0000664 0000000 0000000 00000020771 14600563364 0027256 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_setup_http
short_description: Setup HTTP
description:
Setup HTTP
options:
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
required: no
no_ui_redirect:
description: Do not automatically redirect to the Web UI
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
config_ca_host_name:
description: The config ca_host_name setting
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_ca_enabled:
description: The installer _ca_enabled setting
type: bool
required: no
_ca_file:
description: The installer _ca_file setting
type: str
required: no
_http_pkcs12_info:
description: The installer _http_pkcs12_info setting
type: list
elements: str
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports,
AnsibleModuleLog, setup_logging, installer, DN, paths, sysrestore,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, create_ipa_conf,
install_http, getargspec
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
config_master_host_name=dict(required=True, type='str'),
config_ca_host_name=dict(required=True, type='str'),
ccache=dict(required=True, type='str'),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False, type='str'),
_http_pkcs12_info=dict(required=False, type='list',
elements='str'),
_top_dir=dict(required=True, type='str'),
dirman_password=dict(required=True, type='str', no_log=True),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.no_ui_redirect = ansible_module.params.get('no_ui_redirect')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ca_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
http_pkcs12_info = ansible_module.params.get('_http_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.subject_base = options.subject_base
config.dirman_password = dirman_password
config.setup_ca = options.setup_ca
config.master_host_name = master_host_name
config.ca_host_name = ca_host_name
config.promote = installer.promote
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
# installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
api.Backend.ldap2.connect()
conn.connect(ccache=ccache)
cafile = paths.IPA_CA_CRT
with redirect_stdout(ansible_log):
ansible_log.debug("-- INSTALL_HTTP --")
# We need to point to the master when certmonger asks for
# HTTP certificate.
# During http installation, the HTTP/hostname principal is created
# locally then the installer waits for the entry to appear on the
# master selected for the installation.
# In a later step, the installer requests a SSL certificate through
# Certmonger (and the op adds the principal if it does not exist yet).
# If xmlrpc_uri points to the soon-to-be replica,
# the httpd service is not ready yet to handle certmonger requests
# and certmonger tries to find another master. The master can be
# different from the one selected for the installation, and it is
# possible that the principal has not been replicated yet. This
# may lead to a replication conflict.
# This is why we need to force the use of the same master by
# setting xmlrpc_uri
create_ipa_conf(fstore, config, ca_enabled,
master=config.master_host_name)
# pylint: disable=deprecated-method
argspec = getargspec(install_http)
# pylint: enable=deprecated-method
if "promote" in argspec.args:
install_http(
config,
auto_redirect=not options.no_ui_redirect,
promote=promote,
pkcs12_info=http_pkcs12_info,
ca_is_configured=ca_enabled,
ca_file=cafile)
else:
if "fstore" not in argspec.args:
install_http(
config,
auto_redirect=not options.no_ui_redirect,
pkcs12_info=http_pkcs12_info,
ca_is_configured=ca_enabled,
ca_file=cafile)
else:
install_http(
config,
auto_redirect=not options.no_ui_redirect,
pkcs12_info=http_pkcs12_info,
ca_is_configured=ca_enabled,
ca_file=cafile,
fstore=fstore)
# Need to point back to ourself after the cert for HTTP is obtained
create_ipa_conf(fstore, config, ca_enabled)
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_setup_kra.py 0000664 0000000 0000000 00000026655 14600563364 0027063 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_setup_kra
short_description: Setup KRA
description:
Setup KRA
options:
dm_password:
description: Directory Manager password
type: str
required: no
password:
description: Admin user kerberos password
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: no
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: no
hostname:
description: Fully qualified name of this host
type: str
required: no
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
type: list
elements: str
required: no
no_host_dns:
description: Do not use DNS for hostname lookup during installation
type: bool
default: no
required: no
pki_config_override:
description: Path to ini file with config overrides
type: str
required: no
setup_adtrust:
description: Configure AD trust capability
type: bool
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
setup_dns:
description: Configure bind with our zone
type: bool
required: no
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
type: list
elements: str
required: no
force_join:
description: Force client enrollment even if already enrolled
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
server:
description: Fully qualified name of IPA server to enroll to
type: str
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
installer_ccache:
description: The installer ccache setting
type: str
required: yes
_ca_enabled:
description: The installer _ca_enabled setting
type: bool
required: no
_kra_enabled:
description: The installer _kra_enabled setting
type: bool
required: no
_kra_host_name:
description: The installer _kra_host_name setting
type: str
required: no
_ca_host_name:
description: The installer _ca_host_name setting
type: str
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
_add_to_ipaservers:
description: The installer _add_to_ipaservers setting
type: bool
required: yes
_ca_subject:
description: The installer _ca_subject setting
type: str
required: yes
_subject_base:
description: The installer _subject_base setting
type: str
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
ansible_module_get_parsed_ip_addresses,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, custodiainstance,
kra
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=False, type='str', no_log=True),
password=dict(required=False, type='str', no_log=True),
ip_addresses=dict(required=False, type='list', elements='str',
default=[]),
domain=dict(required=False, type='str'),
realm=dict(required=False, type='str'),
hostname=dict(required=False, type='str'),
ca_cert_files=dict(required=False, type='list', elements='str',
default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
pki_config_override=dict(required=False, type='str'),
# server
setup_adtrust=dict(required=False, type='bool'),
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
setup_dns=dict(required=False, type='bool'),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', elements='str',
default=[]),
# client
force_join=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
server=dict(required=True, type='str'),
config_master_host_name=dict(required=True, type='str'),
installer_ccache=dict(required=True, type='str'),
_ca_enabled=dict(required=False, type='bool'),
_kra_enabled=dict(required=False, type='bool'),
_kra_host_name=dict(required=False, type='str'),
_ca_host_name=dict(required=False, type='str'),
_top_dir=dict(required=True, type='str'),
_add_to_ipaservers=dict(required=True, type='bool'),
_ca_subject=dict(required=True, type='str'),
_subject_base=dict(required=True, type='str'),
dirman_password=dict(required=True, type='str', no_log=True),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
options.dm_password = ansible_module.params.get('dm_password')
options.password = options.dm_password
options.admin_password = ansible_module.params.get('password')
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.no_host_dns = ansible_module.params.get('no_host_dns')
options.pki_config_override = ansible_module.params.get(
'pki_config_override')
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
# client
options.force_join = ansible_module.params.get('force_join')
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options.ca_subject = ansible_module.params.get('ca_subject')
# dns
options.reverse_zones = ansible_module.params.get('reverse_zones')
options.no_reverse = ansible_module.params.get('no_reverse')
options.auto_reverse = ansible_module.params.get('auto_reverse')
options.forwarders = ansible_module.params.get('forwarders')
options.no_forwarders = ansible_module.params.get('no_forwarders')
options.auto_forwarders = ansible_module.params.get('auto_forwarders')
options.forward_policy = ansible_module.params.get('forward_policy')
# additional
options.server = ansible_module.params.get('server')
master_host_name = ansible_module.params.get('config_master_host_name')
os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
kra_enabled = ansible_module.params.get('_kra_enabled')
kra_host_name = ansible_module.params.get('_kra_host_name')
ca_host_name = ansible_module.params.get('_ca_host_name')
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options._top_dir = ansible_module.params.get('_top_dir')
options._add_to_ipaservers = ansible_module.params.get(
'_add_to_ipaservers')
options._ca_subject = ansible_module.params.get('_ca_subject')
options._subject_base = ansible_module.params.get('_subject_base')
dirman_password = ansible_module.params.get('dirman_password')
# init #
ansible_log.debug("== INSTALL ==")
options = installer
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.dirman_password = dirman_password
config.subject_base = options.subject_base
config.promote = installer.promote
config.kra_enabled = kra_enabled
config.kra_host_name = kra_host_name
config.ca_host_name = ca_host_name
config.master_host_name = master_host_name
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
api.Backend.ldap2.connect()
conn.connect(ccache=ccache)
with redirect_stdout(ansible_log):
ansible_log.debug("-- INSTALL KRA --")
if not hasattr(custodiainstance, "get_custodia_instance"):
kra.install(api, config, options)
else:
if ca_enabled:
mode = custodiainstance.CustodiaModes.CA_PEER
else:
mode = custodiainstance.CustodiaModes.MASTER_PEER
custodia = custodiainstance.get_custodia_instance(config, mode)
kra.install(api, config, options, custodia=custodia)
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_setup_krb.py 0000664 0000000 0000000 00000014041 14600563364 0027046 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_setup_krb
short_description: Setup KRB
description:
Setup KRB
options:
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
type: list
elements: str
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports,
AnsibleModuleLog, setup_logging, installer, DN, paths, sysrestore,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, api, redirect_stdout, install_krb, getargspec
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
config_master_host_name=dict(required=True, type='str'),
ccache=dict(required=True, type='str'),
_pkinit_pkcs12_info=dict(required=False, type='list',
elements='str'),
_top_dir=dict(required=True, type='str'),
dirman_password=dict(required=True, type='str', no_log=True),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
installer._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
pkinit_pkcs12_info = installer._pkinit_pkcs12_info
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.dirman_password = dirman_password
config.master_host_name = config_master_host_name
config.subject_base = options.subject_base
config.setup_ca = options.setup_ca
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
api.Backend.ldap2.connect()
ansible_log.debug("-- INSTALL_KRB --")
with redirect_stdout(ansible_log):
# pylint: disable=deprecated-method
argspec = getargspec(install_krb)
# pylint: enable=deprecated-method
if "promote" in argspec.args:
install_krb(
config,
setup_pkinit=not options.no_pkinit,
pkcs12_info=pkinit_pkcs12_info,
promote=promote)
else:
if "fstore" not in argspec.args:
install_krb(
config,
setup_pkinit=not options.no_pkinit,
pkcs12_info=pkinit_pkcs12_info)
else:
install_krb(
config,
setup_pkinit=not options.no_pkinit,
pkcs12_info=pkinit_pkcs12_info,
fstore=fstore)
# done #
ansible_module.exit_json(changed=True,
config_master_host_name=config.master_host_name)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_setup_otpd.py 0000664 0000000 0000000 00000012542 14600563364 0027242 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_setup_otpd
short_description: Setup OTPD
description:
Setup OTPD
options:
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
required: no
no_ui_redirect:
description: Do not automatically redirect to the Web UI
type: bool
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: yes
config_master_host_name:
description: The config master_host_name setting
type: str
required: yes
ccache:
description: The local ccache
type: str
required: yes
_ca_file:
description: The installer _ca_file setting
type: str
required: no
_top_dir:
description: The installer _top_dir setting
type: str
required: yes
dirman_password:
description: Directory Manager (master) password
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, otpdinstance,
ipautil
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True, type='str'),
# additional
config_master_host_name=dict(required=True, type='str'),
ccache=dict(required=True, type='str'),
_ca_file=dict(required=False, type='str'),
_top_dir=dict(required=True, type='str'),
dirman_password=dict(required=True, type='str', no_log=True),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
options = installer
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
# init #
ansible_log.debug("== INSTALL ==")
options = installer
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
config = gen_ReplicaConfig()
config.dirman_password = dirman_password
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
api.Backend.ldap2.connect()
conn.connect(ccache=ccache)
with redirect_stdout(ansible_log):
ansible_log.debug("-- INSTALL_OTPD --")
otpd = otpdinstance.OtpdInstance()
otpd.set_output(ansible_log)
otpd.create_instance('OTPD', config.host_name,
ipautil.realm_to_suffix(config.realm_name))
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/library/ipareplica_test.py 0000664 0000000 0000000 00000050513 14600563364 0026033 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipareplica_test
short_description: IPA replica deployment tests
description: IPA replica deployment tests
options:
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: no
servers:
description: Fully qualified name of IPA servers to enroll to
type: list
elements: str
required: no
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: no
hostname:
description: Fully qualified name of this host
type: str
required: no
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
type: list
elements: str
required: no
hidden_replica:
description: Install a hidden replica
type: bool
default: no
required: no
skip_mem_check:
description: Skip checking for minimum required memory
type: bool
default: no
required: no
setup_adtrust:
description: Configure AD trust capability
type: bool
default: no
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
default: no
required: no
setup_dns:
description: Configure bind with our zone
type: bool
default: no
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
default: no
required: no
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
type: str
required: no
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
type: list
elements: str
required: no
http_cert_files:
description:
File containing the Apache Server SSL certificate and private key
type: list
elements: str
required: no
pkinit_cert_files:
description:
File containing the Kerberos KDC SSL certificate and private key
type: list
elements: str
required: no
no_ntp:
description: Do not configure ntp
type: bool
default: no
required: no
ntp_servers:
description: ntp servers to use
type: list
elements: str
required: no
ntp_pool:
description: ntp server pool to use
type: str
required: no
no_reverse:
description: Do not create new reverse DNS zone
type: bool
default: no
required: no
auto_reverse:
description: Create necessary reverse zones
type: bool
default: no
required: no
forwarders:
description: Add DNS forwarders
type: list
elements: str
required: no
no_forwarders:
description: Do not add any DNS forwarders, use root servers instead
type: bool
default: no
required: no
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
type: bool
default: no
required: no
forward_policy:
description: DNS forwarding policy for global forwarders
type: str
choices: ['first', 'only']
required: no
no_dnssec_validation:
description: Disable DNSSEC validation
type: bool
default: no
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
check_imports, AnsibleModuleLog, setup_logging, options, installer,
paths, sysrestore, ansible_module_get_parsed_ip_addresses, service,
redirect_stdout, create_ipa_conf, ipautil,
x509, validate_domain_name, common_check,
IPA_PYTHON_VERSION, getargspec, adtrustinstance
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
# dm_password=dict(required=False, no_log=True),
# password=dict(required=False, no_log=True),
ip_addresses=dict(required=False, type='list', elements='str',
default=[]),
domain=dict(required=False, type='str'),
servers=dict(required=False, type='list', elements='str',
default=[]),
realm=dict(required=False, type='str'),
hostname=dict(required=False, type='str'),
ca_cert_files=dict(required=False, type='list', elements='str',
default=[]),
hidden_replica=dict(required=False, type='bool', default=False),
skip_mem_check=dict(required=False, type='bool', default=False),
# server
setup_adtrust=dict(required=False, type='bool', default=False),
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool', default=False),
setup_dns=dict(required=False, type='bool', default=False),
no_pkinit=dict(required=False, type='bool', default=False),
dirsrv_config_file=dict(required=False, type='str'),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', elements='str',
default=[]),
http_cert_files=dict(required=False, type='list', elements='str',
default=[]),
pkinit_cert_files=dict(required=False, type='list', elements='str',
default=[]),
# client
no_ntp=dict(required=False, type='bool', default=False),
ntp_servers=dict(required=False, type='list', elements='str',
default=[]),
ntp_pool=dict(required=False, type='str'),
# dns
no_reverse=dict(required=False, type='bool', default=False),
auto_reverse=dict(required=False, type='bool', default=False),
forwarders=dict(required=False, type='list', elements='str',
default=[]),
no_forwarders=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
forward_policy=dict(required=False, type='str',
choices=['first', 'only'], default=None),
no_dnssec_validation=dict(required=False, type='bool',
default=False),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# get parameters #
# basic
# options.dm_password = ansible_module.params.get('dm_password')
# # options.password = ansible_module.params.get('password')
# options.password = options.dm_password
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.domain_name = ansible_module.params.get('domain')
options.servers = ansible_module.params.get('servers')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.hidden_replica = ansible_module.params.get('hidden_replica')
options.skip_mem_check = ansible_module.params.get('skip_mem_check')
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
options.http_cert_files = ansible_module.params.get('http_cert_files')
options.pkinit_cert_files = ansible_module.params.get('pkinit_cert_files')
# client
options.no_ntp = ansible_module.params.get('no_ntp')
options.ntp_servers = ansible_module.params.get('ntp_servers')
options.ntp_pool = ansible_module.params.get('ntp_pool')
# dns
options.no_reverse = ansible_module.params.get('no_reverse')
options.auto_reverse = ansible_module.params.get('auto_reverse')
options.forwarders = ansible_module.params.get('forwarders')
options.no_forwarders = ansible_module.params.get('no_forwarders')
options.auto_forwarders = ansible_module.params.get('auto_forwarders')
options.forward_policy = ansible_module.params.get('forward_policy')
options.no_dnssec_validation = ansible_module.params.get(
'no_dnssec_validation')
##########################################################################
# replica init ###########################################################
##########################################################################
if installer.servers:
installer.server = installer.servers[0]
else:
installer.server = None
# TODO: Kills ipa-client-install
# if installer.replica_file is None:
# installer.password = installer.admin_password
# else:
# installer.password = installer.dm_password
# installer._ccache = os.environ.get('KRB5CCNAME')
# If not defined, set domain from server name
if installer.domain_name is None and installer.server is not None:
installer.domain_name = \
installer.server[installer.server.find(".") + 1:]
# If not defined, set realm from domain name
if installer.realm_name is None and installer.domain_name is not None:
installer.realm_name = installer.domain_name.upper()
##########################################################################
# other checks ###########################################################
##########################################################################
# version specific tests #
# if options.setup_adtrust and not adtrust_imported:
# # if "adtrust" not in options._allow_missing:
# ansible_module.fail_json(msg="adtrust can not be imported")
# # else:
# # options.setup_adtrust = False
# # ansible_module.warn(msg="adtrust is not supported, disabling")
sid_generation_always = False
if not options.setup_adtrust:
# pylint: disable=deprecated-method
argspec = getargspec(adtrustinstance.ADTRUSTInstance.__init__)
# pylint: enable=deprecated-method
if "fulltrust" in argspec.args:
sid_generation_always = True
# if options.setup_kra and not kra_imported:
# # if "kra" not in options._allow_missing:
# ansible_module.fail_json(msg="kra can not be imported")
# # else:
# # options.setup_kra = False
# # ansible_module.warn(msg="kra is not supported, disabling")
if options.hidden_replica and not hasattr(service, "hide_services"):
ansible_module.fail_json(
msg="Hidden replica is not supported in this version.")
# We need to point to the master in ipa default conf when certmonger
# asks for HTTP certificate in newer ipa versions. In these versions
# create_ipa_conf has the additional master argument.
change_master_for_certmonger = False
# pylint: disable=deprecated-method
argspec = getargspec(create_ipa_conf)
# pylint: enable=deprecated-method
if "master" in argspec.args:
change_master_for_certmonger = True
# From ipa installer classes
# pkinit is not supported on DL0, don't allow related options
if installer.replica_file is not None:
ansible_module.fail_json(
msg="Replica installation using a replica file is not supported")
# If any of the key file options are selected, all are required.
cert_file_req = (installer.dirsrv_cert_files, installer.http_cert_files)
cert_file_opt = (installer.pkinit_cert_files,)
if not installer.no_pkinit:
cert_file_req += cert_file_opt
if installer.no_pkinit and installer.pkinit_cert_files:
ansible_module.fail_json(
msg="--no-pkinit and --pkinit-cert-file cannot be specified "
"together")
if any(cert_file_req + cert_file_opt) and not all(cert_file_req):
ansible_module.fail_json(
msg="--dirsrv-cert-file, --http-cert-file, and --pkinit-cert-file "
"or --no-pkinit are required if any key file options are used.")
if not installer.setup_dns:
if installer.forwarders:
ansible_module.fail_json(
msg="You cannot specify a --forwarder option without the "
"--setup-dns option")
if installer.auto_forwarders:
ansible_module.fail_json(
msg="You cannot specify a --auto-forwarders option without "
"the --setup-dns option")
if installer.no_forwarders:
ansible_module.fail_json(
msg="You cannot specify a --no-forwarders option without the "
"--setup-dns option")
if installer.forward_policy:
ansible_module.fail_json(
msg="You cannot specify a --forward-policy option without the "
"--setup-dns option")
if installer.reverse_zones:
ansible_module.fail_json(
msg="You cannot specify a --reverse-zone option without the "
"--setup-dns option")
if installer.auto_reverse:
ansible_module.fail_json(
msg="You cannot specify a --auto-reverse option without the "
"--setup-dns option")
if installer.no_reverse:
ansible_module.fail_json(
msg="You cannot specify a --no-reverse option without the "
"--setup-dns option")
if installer.no_dnssec_validation:
ansible_module.fail_json(
msg="You cannot specify a --no-dnssec-validation option "
"without the --setup-dns option")
elif installer.forwarders and installer.no_forwarders:
ansible_module.fail_json(
msg="You cannot specify a --forwarder option together with "
"--no-forwarders")
elif installer.auto_forwarders and installer.no_forwarders:
ansible_module.fail_json(
msg="You cannot specify a --auto-forwarders option together with "
"--no-forwarders")
elif installer.reverse_zones and installer.no_reverse:
ansible_module.fail_json(
msg="You cannot specify a --reverse-zone option together with "
"--no-reverse")
elif installer.auto_reverse and installer.no_reverse:
ansible_module.fail_json(
msg="You cannot specify a --auto-reverse option together with "
"--no-reverse")
# replica installers
if installer.servers and not installer.domain_name:
ansible_module.fail_json(
msg="The --server option cannot be used without providing "
"domain via the --domain option")
if installer.setup_dns:
if (not installer.forwarders and
not installer.no_forwarders and
not installer.auto_forwarders):
ansible_module.fail_json(
msg="You must specify at least one of --forwarder, "
"--auto-forwarders, or --no-forwarders options")
if installer.dirsrv_config_file is not None and \
not os.path.exists(installer.dirsrv_config_file):
ansible_module.fail_json(
msg="File %s does not exist." % installer.dirsrv_config_file)
if installer.ca_cert_files is not None:
if not isinstance(installer.ca_cert_files, list):
ansible_module.fail_json(
msg="Expected list, got {0!r}".format(installer.ca_cert_files))
for cert in installer.ca_cert_files:
if not os.path.exists(cert):
ansible_module.fail_json(msg="'%s' does not exist" % cert)
if not os.path.isfile(cert):
ansible_module.fail_json(msg="'%s' is not a file" % cert)
if not os.path.isabs(cert):
ansible_module.fail_json(
msg="'%s' is not an absolute file path" % cert)
try:
x509.load_certificate_from_file(cert)
except Exception:
ansible_module.fail_json(
msg="'%s' is not a valid certificate file" % cert)
if installer.ip_addresses is not None:
for value in installer.ip_addresses:
try:
ipautil.CheckedIPAddress(value)
except Exception as e:
ansible_module.fail_json(
msg="invalid IP address {0}: {1}".format(
value, e))
if installer.domain_name is not None:
validate_domain_name(installer.domain_name)
##########################################################################
# replica promote_check excerpts #########################################
##########################################################################
# check selinux status, http and DS ports, NTP conflicting services
try:
with redirect_stdout(ansible_log):
# pylint: disable=deprecated-method
argspec = getargspec(common_check)
# pylint: enable=deprecated-method
if "skip_mem_check" in argspec.args:
common_check(options.no_ntp, options.skip_mem_check,
options.setup_ca)
else:
common_check(options.no_ntp)
except Exception as msg: # ScriptError as msg:
_msg = str(msg)
if "server is already configured" in _msg:
ansible_module.exit_json(changed=False,
server_already_configured=True)
else:
ansible_module.fail_json(msg=_msg)
# TODO: Check ntp_servers and ntp_pool
# client enrolled?
client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
client_enrolled = client_fstore.has_files()
if not client_enrolled:
# # One-step replica installation
# if options.dm_password and options.password:
# ansible_module.fail_json(
# msg="--password and --admin-password options are "
# "mutually exclusive")
pass
else:
# The NTP configuration can not be touched on pre-installed client:
if options.no_ntp or options.ntp_servers or options.ntp_pool:
ansible_module.fail_json(
msg="NTP configuration cannot be updated during promotion")
# host_name an domain_name must be different at this point.
if options.host_name.lower() == options.domain_name.lower():
ansible_module.fail_json(
msg="hostname cannot be the same as the domain name")
# done #
ansible_module.exit_json(
changed=False,
ipa_python_version=IPA_PYTHON_VERSION,
# basic
domain=options.domain_name,
realm=options.realm_name,
hostname=options.host_name,
# server
setup_adtrust=options.setup_adtrust,
setup_kra=options.setup_kra,
server=options.server,
# additional
client_enrolled=client_enrolled,
change_master_for_certmonger=change_master_for_certmonger,
sid_generation_always=sid_generation_always
)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipareplica/meta/ 0000775 0000000 0000000 00000000000 14600563364 0021567 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipareplica/meta/main.yml 0000664 0000000 0000000 00000000523 14600563364 0023236 0 ustar 00root root 0000000 0000000 ---
dependencies: []
galaxy_info:
author: Thomas Woerner
description: A role to setup an IPA domain replica
company: Red Hat, Inc
license: GPLv3
min_ansible_version: "2.13"
platforms:
- name: Fedora
versions:
- all
- name: EL
versions:
- "7"
- "8"
galaxy_tags:
- identity
- ipa
- freeipa
ansible-freeipa-master/roles/ipareplica/module_utils/ 0000775 0000000 0000000 00000000000 14600563364 0023346 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipareplica/module_utils/ansible_ipa_replica.py 0000664 0000000 0000000 00000042754 14600563364 0027701 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
__all__ = ["contextlib", "dnsexception", "dnsresolver", "dnsreversename",
"parse_version", "IPAChangeConf",
"certstore", "sysrestore", "ipa_generate_password", "kinit_keytab",
"IPA_CA_TRUST_FLAGS", "EXTERNAL_CA_TRUST_FLAGS", "DN",
"ScriptError", "services", "tasks", "constants", "errors", "rpc",
"x509", "validate_domain_name",
"no_matching_interface_for_ip_address_warning",
"configure_krb5_conf", "purge_host_keytab", "adtrust",
"bindinstance", "ca", "certs", "dns", "httpinstance", "kra",
"otpdinstance", "custodiainstance", "service", "upgradeinstance",
"find_providing_servers", "find_providing_server", "load_pkcs12",
"is_ipa_configured", "ReplicationManager", "replica_conn_check",
"install_replica_ds", "install_krb", "install_ca_cert",
"install_http", "install_dns_records", "create_ipa_conf",
"check_dirsrv", "check_dns_resolution", "configure_certmonger",
"remove_replica_info_dir", "preserve_enrollment_state",
"uninstall_client", "promote_sssd", "promote_openldap_conf",
"rpc_client", "check_remote_fips_mode", "check_remote_version",
"common_check", "current_domain_level",
"check_domain_level_is_supported", "promotion_check_ipa_domain",
"SSSDConfig", "CalledProcessError", "timeconf", "ntpinstance",
"dnsname", "kernel_keyring", "krbinstance", "getargspec",
"adtrustinstance", "paths", "api", "dsinstance", "ipaldap", "Env",
"ipautil", "installutils", "IPA_PYTHON_VERSION", "NUM_VERSION",
"ReplicaConfig", "create_api"]
import sys
import logging
# Import getargspec from inspect or provide own getargspec for
# Python 2 compatibility with Python 3.11+.
try:
from inspect import getargspec
except ImportError:
from collections import namedtuple
from inspect import getfullargspec
# The code is copied from Python 3.10 inspect.py
# Authors: Ka-Ping Yee
# Yury Selivanov
ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults')
def getargspec(func):
args, varargs, varkw, defaults, kwonlyargs, _kwonlydefaults, \
ann = getfullargspec(func)
if kwonlyargs or ann:
raise ValueError(
"Function has keyword-only parameters or annotations"
", use inspect.signature() API which can support them")
return ArgSpec(args, varargs, varkw, defaults)
try:
from contextlib import contextmanager as contextlib_contextmanager
from ipapython.version import NUM_VERSION, VERSION
if NUM_VERSION < 30201:
# See ipapython/version.py
IPA_MAJOR, IPA_MINOR, IPA_RELEASE = [int(x) for x in
VERSION.split(".", 2)]
IPA_PYTHON_VERSION = IPA_MAJOR * 10000 + IPA_MINOR * 100 + IPA_RELEASE
else:
IPA_PYTHON_VERSION = NUM_VERSION
if NUM_VERSION >= 40600:
# IPA version >= 4.6
import contextlib
import dns.exception as dnsexception
import dns.name as dnsname
import dns.resolver as dnsresolver
import dns.reversename as dnsreversename
from pkg_resources import parse_version
from ipaclient.install.ipachangeconf import IPAChangeConf
from ipalib.install import certstore, sysrestore
from ipapython.ipautil import ipa_generate_password
from ipalib.install.kinit import kinit_keytab
from ipapython import ipaldap, ipautil, kernel_keyring
from ipapython.certdb import IPA_CA_TRUST_FLAGS, \
EXTERNAL_CA_TRUST_FLAGS
from ipapython.dn import DN
from ipapython.admintool import ScriptError
from ipapython.ipa_log_manager import standard_logging_setup
from ipaplatform import services
from ipaplatform.tasks import tasks
from ipaplatform.paths import paths
from ipalib import api, constants, create_api, errors, rpc, x509
from ipalib.config import Env
from ipalib.util import (
validate_domain_name,
no_matching_interface_for_ip_address_warning)
from ipaclient.install.client import configure_krb5_conf, \
purge_host_keytab
from ipaserver.install import (
adtrust, bindinstance, ca, certs, dns, dsinstance, httpinstance,
installutils, kra, krbinstance,
otpdinstance, custodiainstance, service, upgradeinstance)
from ipaserver.install import adtrustinstance
try:
from ipaserver.masters import (
find_providing_servers, find_providing_server)
except ImportError:
from ipaserver.install.service import (
find_providing_servers, find_providing_server)
from ipaserver.install.installutils import (
ReplicaConfig, load_pkcs12)
try:
from ipalib.facts import is_ipa_configured
except ImportError:
from ipaserver.install.installutils import is_ipa_configured
from ipaserver.install.replication import (
ReplicationManager, replica_conn_check)
from ipaserver.install.server.replicainstall import (
make_pkcs12_info, install_replica_ds, install_krb, install_ca_cert,
install_http, install_dns_records, create_ipa_conf, check_dirsrv,
check_dns_resolution, configure_certmonger,
remove_replica_info_dir,
# common_cleanup,
preserve_enrollment_state, uninstall_client,
promote_sssd, promote_openldap_conf, rpc_client,
check_remote_fips_mode, check_remote_version, common_check,
current_domain_level, check_domain_level_is_supported,
# enroll_dl0_replica,
# ensure_enrolled,
promotion_check_ipa_domain
)
import SSSDConfig
from subprocess import CalledProcessError
try:
from ipaclient.install import timeconf
time_service = "chronyd" # pylint: disable=invalid-name
ntpinstance = None # pylint: disable=invalid-name
except ImportError:
try:
from ipaclient.install import ntpconf as timeconf
except ImportError:
from ipaclient import ntpconf as timeconf
from ipaserver.install import ntpinstance
time_service = "ntpd" # pylint: disable=invalid-name
else:
# IPA version < 4.6
raise RuntimeError("freeipa version '%s' is too old" % VERSION)
except ImportError as _err:
ANSIBLE_IPA_REPLICA_MODULE_IMPORT_ERROR = str(_err)
for attr in __all__:
setattr(sys.modules[__name__], attr, None)
else:
ANSIBLE_IPA_REPLICA_MODULE_IMPORT_ERROR = None
logger = logging.getLogger("ipa-server-install")
def setup_logging():
# logger.setLevel(logging.DEBUG)
standard_logging_setup(
paths.IPAREPLICA_INSTALL_LOG, verbose=False, debug=False,
filemode='a', console_format='%(message)s')
@contextlib_contextmanager
def redirect_stdout(stream):
sys.stdout = stream
try:
yield stream
finally:
sys.stdout = sys.__stdout__
class AnsibleModuleLog():
def __init__(self, module):
self.module = module
_ansible_module_log = self
class AnsibleLoggingHandler(logging.Handler):
def emit(self, record):
_ansible_module_log.write(self.format(record))
self.logging_handler = AnsibleLoggingHandler()
logger.setLevel(logging.DEBUG)
logger.root.addHandler(self.logging_handler)
def close(self):
self.flush()
def flush(self):
pass
def log(self, msg):
# self.write(msg+"\n")
self.write(msg)
def debug(self, msg):
self.module.debug(msg)
def info(self, msg):
self.module.debug(msg)
@staticmethod
def isatty():
return False
def write(self, msg):
self.module.debug(msg)
# self.module.warn(msg)
# pylint: disable=too-many-instance-attributes, useless-object-inheritance
class installer_obj(object): # pylint: disable=invalid-name
def __init__(self):
# CompatServerReplicaInstall
self.ca_cert_files = None
self.all_ip_addresses = False
self.no_wait_for_dns = True
self.nisdomain = None
self.no_nisdomain = False
self.no_sudo = False
self.request_cert = False
self.ca_file = None
self.zonemgr = None
self.replica_file = None
# ServerReplicaInstall
self.subject_base = None
self.ca_subject = None
# others
self._ccache = None
self.password = None
self.reverse_zones = []
# def _is_promote(self):
# return self.replica_file is None
# self.skip_conncheck = False
self._replica_install = False
# self.dnssec_master = False # future unknown
# self.disable_dnssec_master = False # future unknown
# self.domainlevel = MAX_DOMAIN_LEVEL # deprecated
# self.domain_level = self.domainlevel # deprecated
self.interactive = False
self.unattended = not self.interactive
# self.promote = self.replica_file is None
self.promote = True
self.skip_schema_check = None
# def __getattribute__(self, attr):
# value = super(installer_obj, self).__getattribute__(attr)
# if not attr.startswith("--") and not attr.endswith("--"):
# logger.debug(
# " <-- Accessing installer.%s (%s)" %
# (attr, repr(value)))
# return value
def __getattr__(self, attrname):
logger.info(" --> ADDING missing installer.%s", attrname)
setattr(self, attrname, None)
return getattr(self, attrname)
# def __setattr__(self, attr, value):
# logger.debug(" --> Setting installer.%s to %s" %
# (attr, repr(value)))
# return super(installer_obj, self).__setattr__(attr, value)
def knobs(self):
for name in self.__dict__:
yield self, name
# pylint: enable=too-many-instance-attributes, useless-object-inheritance
# pylint: disable=attribute-defined-outside-init
installer = installer_obj()
options = installer
# DNSInstallInterface
options.dnssec_master = False
options.disable_dnssec_master = False
options.kasp_db_file = None
options.force = False
# ServerMasterInstall
options.add_sids = False
options.add_agents = False
# ServerReplicaInstall
options.subject_base = None
options.ca_subject = None
# pylint: enable=attribute-defined-outside-init
def gen_env_boostrap_finalize_core(etc_ipa, default_config):
env = Env()
# env._bootstrap(context='installer', confdir=paths.ETC_IPA, log=None)
# env._finalize_core(**dict(constants.DEFAULT_CONFIG))
env._bootstrap(context='installer', confdir=etc_ipa, log=None)
env._finalize_core(**dict(default_config))
return env
def api_bootstrap_finalize(env):
# pylint: disable=no-member
xmlrpc_uri = \
'https://{0}/ipa/xml'.format(ipautil.format_netloc(env.host))
api.bootstrap(in_server=True,
context='installer',
confdir=paths.ETC_IPA,
ldap_uri=installutils.realm_to_ldapi_uri(env.realm),
xmlrpc_uri=xmlrpc_uri)
# pylint: enable=no-member
api.finalize()
def gen_ReplicaConfig(): # pylint: disable=invalid-name
# pylint: disable=too-many-instance-attributes
class ExtendedReplicaConfig(ReplicaConfig):
# pylint: disable=useless-super-delegation
def __init__(self, top_dir=None):
# pylint: disable=super-with-arguments
super(ExtendedReplicaConfig, self).__init__(top_dir)
# def __getattribute__(self, attr):
# value = super(ExtendedReplicaConfig, self).__getattribute__(
# attr)
# if attr not in ["__dict__", "knobs"]:
# logger.debug(" <== Accessing config.%s (%s)" %
# (attr, repr(value)))
# return value\
# pylint: enable=useless-super-delegation
def __getattr__(self, attrname):
logger.info(" ==> ADDING missing config.%s", attrname)
setattr(self, attrname, None)
return getattr(self, attrname)
# def __setattr__(self, attr, value):
# logger.debug(" ==> Setting config.%s to %s" %
# (attr, repr(value)))
# return super(ExtendedReplicaConfig, self).__setattr__(attr,
# value)
def knobs(self):
for name in self.__dict__:
yield self, name
# pylint: enable=too-many-instance-attributes
# pylint: disable=attribute-defined-outside-init
# config = ReplicaConfig()
config = ExtendedReplicaConfig()
config.realm_name = api.env.realm
config.host_name = api.env.host
config.domain_name = api.env.domain
config.master_host_name = api.env.server
config.ca_host_name = api.env.ca_host
config.kra_host_name = config.ca_host_name
config.ca_ds_port = 389
config.setup_ca = options.setup_ca
config.setup_kra = options.setup_kra
config.dir = options._top_dir
config.basedn = api.env.basedn
# config.subject_base = options.subject_base
# pylint: enable=attribute-defined-outside-init
return config
def replica_ds_init_info(ansible_log,
config, options_, ca_is_configured, remote_api,
ds_ca_subject, ca_file,
promote=False, pkcs12_info=None):
dsinstance.check_ports()
# if we have a pkcs12 file, create the cert db from
# that. Otherwise the ds setup will create the CA
# cert
if pkcs12_info is None:
pkcs12_info = make_pkcs12_info(config.dir, "dscert.p12",
"dirsrv_pin.txt")
# during replica install, this gets invoked before local DS is
# available, so use the remote api.
# if ca_is_configured:
# ca_subject = ca.lookup_ca_subject(_api, config.subject_base)
# else:
# ca_subject = installutils.default_ca_subject_dn(
# config.subject_base)
ca_subject = ds_ca_subject
ds = dsinstance.DsInstance(
config_ldif=options_.dirsrv_config_file)
ds.set_output(ansible_log)
# Source: ipaserver/install/dsinstance.py
# idstart and idmax are configured so that the range is seen as
# depleted by the DNA plugin and the replica will go and get a
# new range from the master.
# This way all servers use the initially defined range by default.
idstart = 1101
idmax = 1100
with redirect_stdout(ansible_log):
ds.init_info(
realm_name=config.realm_name,
fqdn=config.host_name,
domain_name=config.domain_name,
dm_password=config.dirman_password,
subject_base=config.subject_base,
ca_subject=ca_subject,
idstart=idstart,
idmax=idmax,
pkcs12_info=pkcs12_info,
ca_file=ca_file,
setup_pkinit=not options.no_pkinit,
)
ds.master_fqdn = config.master_host_name
if ca_is_configured is not None:
ds.ca_is_configured = ca_is_configured
ds.promote = promote
ds.api = remote_api
# from __setup_replica
# Always connect to ds over ldapi
ldap_uri = ipaldap.get_ldap_uri(protocol='ldapi', realm=ds.realm)
conn = ipaldap.LDAPClient(ldap_uri)
conn.external_bind()
return ds
def ansible_module_get_parsed_ip_addresses(ansible_module,
param='ip_addresses'):
ip_addrs = []
for ip in ansible_module.params.get(param):
try:
ip_parsed = ipautil.CheckedIPAddress(ip)
except Exception as e:
ansible_module.fail_json(
msg="Invalid IP Address %s: %s" % (ip, e))
ip_addrs.append(ip_parsed)
return ip_addrs
def gen_remote_api(master_host_name, etc_ipa):
ldapuri = 'ldaps://%s' % ipautil.format_netloc(master_host_name)
xmlrpc_uri = 'https://{0}/ipa/xml'.format(
ipautil.format_netloc(master_host_name))
remote_api = create_api(mode=None)
remote_api.bootstrap(in_server=True,
context='installer',
confdir=etc_ipa,
ldap_uri=ldapuri,
xmlrpc_uri=xmlrpc_uri)
remote_api.finalize()
return remote_api
def check_imports(module):
if ANSIBLE_IPA_REPLICA_MODULE_IMPORT_ERROR is not None:
module.fail_json(msg=ANSIBLE_IPA_REPLICA_MODULE_IMPORT_ERROR)
ansible-freeipa-master/roles/ipareplica/tasks/ 0000775 0000000 0000000 00000000000 14600563364 0021766 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipareplica/tasks/install.yml 0000664 0000000 0000000 00000110713 14600563364 0024162 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipareplica
- name: Package installation
when: ipareplica_install_packages | bool
block:
- name: Install - Ensure IPA replica packages are installed
ansible.builtin.package:
name: "{{ ipareplica_packages }}"
state: present
- name: Install - Ensure IPA replica packages for dns are installed
ansible.builtin.package:
name: "{{ ipareplica_packages_dns }}"
state: present
when: ipareplica_setup_dns | bool
- name: Install - Ensure IPA replica packages for adtrust are installed
ansible.builtin.package:
name: "{{ ipareplica_packages_adtrust }}"
state: present
when: ipareplica_setup_adtrust | bool
- name: Install - Ensure that firewall packages installed
ansible.builtin.package:
name: "{{ ipareplica_packages_firewalld }}"
state: present
when: ipareplica_setup_firewalld | bool
- name: Firewall configuration
when: ipareplica_setup_firewalld | bool
block:
- name: Firewalld service - Ensure that firewalld is running
ansible.builtin.systemd:
name: firewalld
enabled: yes
state: started
- name: Firewalld - Verify runtime zone "{{ ipareplica_firewalld_zone }}"
ansible.builtin.shell: >
firewall-cmd
--info-zone="{{ ipareplica_firewalld_zone }}"
>/dev/null
when: ipareplica_firewalld_zone is defined
- name: Firewalld - Verify permanent zone "{{ ipareplica_firewalld_zone }}"
ansible.builtin.shell: >
firewall-cmd
--permanent
--info-zone="{{ ipareplica_firewalld_zone }}"
>/dev/null
when: ipareplica_firewalld_zone is defined
- name: Install - Set ipareplica_servers
ansible.builtin.set_fact:
ipareplica_servers: "{{ groups['ipaservers'] | list }}"
when: groups.ipaservers is defined and ipareplica_servers is not defined
- name: Install - Set ipareplica_servers from cluster inventory
ansible.builtin.set_fact:
ipareplica_servers: "{{ groups['ipaserver'] | list }}"
when: ipareplica_servers is not defined and groups.ipaserver is defined
- name: Install - Set default principal if no keytab is given
ansible.builtin.set_fact:
ipaadmin_principal: admin
when: ipaadmin_principal is undefined and ipaclient_keytab is undefined
- name: Install - Replica installation test
ipareplica_test:
### basic ###
# dm_password: "{{ ipadm_password | default(omit) }}"
# password: "{{ ipaadmin_password | default(omit) }}"
ip_addresses: "{{ ipareplica_ip_addresses | default([]) }}"
domain: "{{ ipareplica_domain | default(ipaserver_domain) |
default(omit) }}"
servers: "{{ ipareplica_servers | default(omit) }}"
realm: "{{ ipareplica_realm | default(ipaserver_realm) | default(omit) }}"
hostname: "{{ ipareplica_hostname | default(ansible_facts['fqdn']) }}"
ca_cert_files: "{{ ipareplica_ca_cert_files | default([]) }}"
hidden_replica: "{{ ipareplica_hidden_replica }}"
skip_mem_check: "{{ not ipareplica_mem_check }}"
### server ###
setup_adtrust: "{{ ipareplica_setup_adtrust }}"
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ ipareplica_setup_kra }}"
setup_dns: "{{ ipareplica_setup_dns }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
dirsrv_config_file: "{{ ipareplica_dirsrv_config_file | default(omit) }}"
### ssl certificate ###
dirsrv_cert_files: "{{ ipareplica_dirsrv_cert_files | default([]) }}"
http_cert_files: "{{ ipareplica_http_cert_files | default([]) }}"
pkinit_cert_files: "{{ ipareplica_pkinit_cert_files | default([]) }}"
### client ###
no_ntp: "{{ ipaclient_no_ntp }}"
ntp_servers: "{{ ipaclient_ntp_servers | default([]) }}"
ntp_pool: "{{ ipaclient_ntp_pool | default(omit) }}"
### dns ###
no_reverse: "{{ ipareplica_no_reverse }}"
auto_reverse: "{{ ipareplica_auto_reverse }}"
forwarders: "{{ ipareplica_forwarders | default([]) }}"
no_forwarders: "{{ ipareplica_no_forwarders }}"
auto_forwarders: "{{ ipareplica_auto_forwarders }}"
forward_policy: "{{ ipareplica_forward_policy | default(omit) }}"
no_dnssec_validation: "{{ ipareplica_no_dnssec_validation }}"
register: result_ipareplica_test
- name: Install - Deploy replica
when: not ansible_check_mode and
not (result_ipareplica_test.client_already_configured is defined or
result_ipareplica_test.server_already_configured is defined)
block:
# This block is executed only when
# not ansible_check_mode and
# not (result_ipareplica_test.client_already_configured is defined or
# result_ipareplica_test.server_already_configured is defined)
- name: Install - Setup client
ansible.builtin.include_role:
name: ipaclient
vars:
state: present
ipaclient_domain: "{{ result_ipareplica_test.domain | default(omit) }}"
ipaclient_realm: "{{ result_ipareplica_test.realm | default(omit) }}"
ipaclient_servers: "{{ ipareplica_servers | default(omit) }}"
ipaclient_hostname: "{{ result_ipareplica_test.hostname }}"
ipaclient_install_packages: "{{ ipareplica_install_packages }}"
when: not result_ipareplica_test.client_enrolled
- name: Install - Configure firewalld
ansible.builtin.command: >
firewall-cmd
--permanent
--zone="{{ ipareplica_firewalld_zone if ipareplica_firewalld_zone is
defined else '' }}"
--add-service=freeipa-ldap
--add-service=freeipa-ldaps
{{ "--add-service=freeipa-trust" if result_ipareplica_test.setup_adtrust
else "" }}
{{ "--add-service=dns" if ipareplica_setup_dns | bool else "" }}
{{ "--add-service=ntp" if not ipaclient_no_ntp | bool else "" }}
when: ipareplica_setup_firewalld | bool
- name: Install - Configure firewalld runtime
ansible.builtin.command: >
firewall-cmd
--zone="{{ ipareplica_firewalld_zone if ipareplica_firewalld_zone is
defined else '' }}"
--add-service=freeipa-ldap
--add-service=freeipa-ldaps
{{ "--add-service=freeipa-trust" if result_ipareplica_test.setup_adtrust
else "" }}
{{ "--add-service=dns" if ipareplica_setup_dns | bool else "" }}
{{ "--add-service=ntp" if not ipaclient_no_ntp | bool else "" }}
when: ipareplica_setup_firewalld | bool
- name: Install - Replica preparation
ipareplica_prepare:
### basic ###
password: "{{ ipaadmin_password | default(omit) }}"
ip_addresses: "{{ ipareplica_ip_addresses | default([]) }}"
domain: "{{ result_ipareplica_test.domain }}"
realm: "{{ result_ipareplica_test.realm }}"
hostname: "{{ result_ipareplica_test.hostname }}"
principal: "{{ ipaadmin_principal | default(omit) }}"
ca_cert_files: "{{ ipareplica_ca_cert_files | default([]) }}"
no_host_dns: "{{ ipareplica_no_host_dns }}"
### replica ###
setup_adtrust: "{{ result_ipareplica_test.setup_adtrust }}"
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
setup_dns: "{{ ipareplica_setup_dns }}"
### ssl certificate ###
dirsrv_cert_files: "{{ ipareplica_dirsrv_cert_files | default([]) }}"
dirsrv_cert_name: "{{ ipareplica_dirsrv_cert_name | default(omit) }}"
dirsrv_pin: "{{ ipareplica_dirsrv_pin | default(omit) }}"
http_cert_files: "{{ ipareplica_http_cert_files | default([]) }}"
http_cert_name: "{{ ipareplica_http_cert_name | default(omit) }}"
http_pin: "{{ ipareplica_http_pin | default(omit) }}"
pkinit_cert_files: "{{ ipareplica_pkinit_cert_files | default([]) }}"
pkinit_cert_name: "{{ ipareplica_pkinit_cert_name | default(omit) }}"
pkinit_pin: "{{ ipareplica_pkinit_pin | default(omit) }}"
### client ###
keytab: "{{ ipaclient_keytab | default(omit) }}"
mkhomedir: "{{ ipaclient_mkhomedir | default(omit) }}"
force_join: "{{ ipaclient_force_join | default(omit) }}"
no_ntp: "{{ ipaclient_no_ntp | default(omit) }}"
ssh_trust_dns: "{{ ipaclient_ssh_trust_dns | default(omit) }}"
no_ssh: no
no_sshd: no
no_dns_sshfp: no
### dns ###
allow_zone_overlap: "{{ ipareplica_allow_zone_overlap }}"
reverse_zones: "{{ ipareplica_reverse_zones | default([]) }}"
no_reverse: "{{ ipareplica_no_reverse }}"
auto_reverse: "{{ ipareplica_auto_reverse }}"
forwarders: "{{ ipareplica_forwarders | default([]) }}"
no_forwarders: "{{ ipareplica_no_forwarders }}"
auto_forwarders: "{{ ipareplica_auto_forwarders }}"
forward_policy: "{{ ipareplica_forward_policy | default(omit) }}"
no_dnssec_validation: "{{ ipareplica_no_dnssec_validation }}"
### ad trust ###
enable_compat: "{{ ipareplica_enable_compat }}"
netbios_name: "{{ ipareplica_netbios_name | default(omit) }}"
rid_base: "{{ ipareplica_rid_base | default(omit) }}"
secondary_rid_base: "{{ ipareplica_secondary_rid_base | default(omit) }}"
### additional ###
server: "{{ result_ipareplica_test.server }}"
skip_conncheck: "{{ ipareplica_skip_conncheck }}"
sid_generation_always: "{{ result_ipareplica_test.sid_generation_always }}"
register: result_ipareplica_prepare
- name: Install - Add to ipaservers
ipareplica_add_to_ipaservers:
### server ###
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
### additional ###
config_master_host_name:
"{{ result_ipareplica_prepare.config_master_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
when: result_ipareplica_prepare._add_to_ipaservers
- name: Install - Create dirman password
no_log: yes
ipareplica_master_password:
master_password: "{{ ipareplica_master_password | default(omit) }}"
register: result_ipareplica_master_password
- name: Install - Set dirman password
no_log: yes
ansible.builtin.set_fact:
__derived_dirman_password:
"{{ result_ipareplica_master_password.password }}"
- name: Install - Setup certmonger
ipareplica_setup_certmonger:
when: result_ipareplica_prepare._ca_enabled
- name: Install - Install CA certs
ipareplica_install_ca_certs:
### basic ###
dm_password: "{{ ipadm_password | default(omit) }}"
password: "{{ ipaadmin_password | default(omit) }}"
ip_addresses: "{{ ipareplica_ip_addresses | default([]) }}"
domain: "{{ result_ipareplica_test.domain }}"
realm: "{{ result_ipareplica_test.realm }}"
hostname: "{{ result_ipareplica_test.hostname }}"
ca_cert_files: "{{ ipareplica_ca_cert_files | default([]) }}"
no_host_dns: "{{ ipareplica_no_host_dns }}"
### replica ###
setup_adtrust: "{{ result_ipareplica_test.setup_adtrust }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
setup_dns: "{{ ipareplica_setup_dns }}"
### server ###
setup_ca: "{{ ipareplica_setup_ca }}"
### ssl certificate ###
dirsrv_cert_files: "{{ ipareplica_dirsrv_cert_files | default([]) }}"
### client ###
force_join: "{{ ipaclient_force_join }}"
### additional ###
server: "{{ result_ipareplica_test.server }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
dirman_password: "{{ __derived_dirman_password }}"
config_setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
config_master_host_name:
"{{ result_ipareplica_prepare.config_master_host_name }}"
config_ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
config_ips: "{{ result_ipareplica_prepare.config_ips }}"
register: result_ipareplica_install_ca_certs
- name: Install - Setup DS
ipareplica_setup_ds:
### basic ###
dm_password: "{{ ipadm_password | default(omit) }}"
password: "{{ ipaadmin_password | default(omit) }}"
ip_addresses: "{{ ipareplica_ip_addresses | default([]) }}"
domain: "{{ result_ipareplica_test.domain }}"
realm: "{{ result_ipareplica_test.realm }}"
hostname: "{{ result_ipareplica_test.hostname }}"
ca_cert_files: "{{ ipareplica_ca_cert_files | default([]) }}"
no_host_dns: "{{ ipareplica_no_host_dns }}"
### replica ###
setup_adtrust: "{{ result_ipareplica_test.setup_adtrust }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
setup_dns: "{{ ipareplica_setup_dns }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
dirsrv_config_file: "{{ ipareplica_dirsrv_config_file | default(omit) }}"
### ssl certificate ###
dirsrv_cert_files: "{{ ipareplica_dirsrv_cert_files | default([]) }}"
### client ###
force_join: "{{ ipaclient_force_join }}"
### additional ###
server: "{{ result_ipareplica_test.server }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_dirsrv_pkcs12_info: "{{ result_ipareplica_prepare._dirsrv_pkcs12_info if result_ipareplica_prepare._dirsrv_pkcs12_info != None else omit }}"
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
dirman_password: "{{ __derived_dirman_password }}"
config_setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
config_ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
config_ips: "{{ result_ipareplica_prepare.config_ips }}"
register: result_ipareplica_setup_ds
- name: Install - Create IPA conf
ipareplica_create_ipa_conf:
### basic ###
dm_password: "{{ ipadm_password | default(omit) }}"
password: "{{ ipaadmin_password | default(omit) }}"
ip_addresses: "{{ ipareplica_ip_addresses | default([]) }}"
domain: "{{ result_ipareplica_test.domain }}"
realm: "{{ result_ipareplica_test.realm }}"
hostname: "{{ result_ipareplica_test.hostname }}"
ca_cert_files: "{{ ipareplica_ca_cert_files | default([]) }}"
no_host_dns: "{{ ipareplica_no_host_dns }}"
### replica ###
setup_adtrust: "{{ result_ipareplica_test.setup_adtrust }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
setup_dns: "{{ ipareplica_setup_dns }}"
### ssl certificate ###
dirsrv_cert_files: "{{ ipareplica_dirsrv_cert_files | default([]) }}"
### client ###
force_join: "{{ ipaclient_force_join }}"
### additional ###
server: "{{ result_ipareplica_test.server }}"
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
config_ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
dirman_password: "{{ __derived_dirman_password }}"
setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
- name: Install - Setup KRB
ipareplica_setup_krb:
### server ###
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ __derived_dirman_password }}"
# We need to point to the master in ipa default conf when certmonger
# asks for HTTP certificate in newer ipa versions. In these versions
# create_ipa_conf has the additional master argument.
- name: Install - Create override IPA conf
ipareplica_create_ipa_conf:
### basic ###
dm_password: "{{ ipadm_password | default(omit) }}"
password: "{{ ipaadmin_password | default(omit) }}"
ip_addresses: "{{ ipareplica_ip_addresses | default([]) }}"
domain: "{{ result_ipareplica_test.domain }}"
realm: "{{ result_ipareplica_test.realm }}"
hostname: "{{ result_ipareplica_test.hostname }}"
ca_cert_files: "{{ ipareplica_ca_cert_files | default([]) }}"
no_host_dns: "{{ ipareplica_no_host_dns }}"
### replica ###
setup_adtrust: "{{ result_ipareplica_test.setup_adtrust }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
setup_dns: "{{ ipareplica_setup_dns }}"
### ssl certificate ###
dirsrv_cert_files: "{{ ipareplica_dirsrv_cert_files | default([]) }}"
### client ###
force_join: "{{ ipaclient_force_join }}"
### additional ###
server: "{{ result_ipareplica_test.server }}"
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
config_ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
dirman_password: "{{ __derived_dirman_password }}"
setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
master:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
when: result_ipareplica_test.change_master_for_certmonger
- name: Install - DS enable SSL
ipareplica_ds_enable_ssl:
### server ###
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
dirsrv_config_file: "{{ ipareplica_dirsrv_config_file | default(omit) }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_dirsrv_pkcs12_info: "{{ result_ipareplica_prepare._dirsrv_pkcs12_info if result_ipareplica_prepare._dirsrv_pkcs12_info != None else omit }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ __derived_dirman_password }}"
ds_ca_subject: "{{ result_ipareplica_setup_ds.ds_ca_subject }}"
- name: Install - Setup http
ipareplica_setup_http:
### server ###
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
no_ui_redirect: "{{ ipareplica_no_ui_redirect }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
config_ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_http_pkcs12_info: "{{ result_ipareplica_prepare._http_pkcs12_info if result_ipareplica_prepare._http_pkcs12_info != None else omit }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ __derived_dirman_password }}"
# Need to point back to ourself after the cert for HTTP is obtained
- name: Install - Create original IPA conf again
ipareplica_create_ipa_conf:
### basic ###
dm_password: "{{ ipadm_password | default(omit) }}"
password: "{{ ipaadmin_password | default(omit) }}"
ip_addresses: "{{ ipareplica_ip_addresses | default([]) }}"
domain: "{{ result_ipareplica_test.domain }}"
realm: "{{ result_ipareplica_test.realm }}"
hostname: "{{ result_ipareplica_test.hostname }}"
ca_cert_files: "{{ ipareplica_ca_cert_files | default([]) }}"
no_host_dns: "{{ ipareplica_no_host_dns }}"
### replica ###
setup_adtrust: "{{ result_ipareplica_test.setup_adtrust }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
setup_dns: "{{ ipareplica_setup_dns }}"
### ssl certificate ###
dirsrv_cert_files: "{{ ipareplica_dirsrv_cert_files | default([]) }}"
### client ###
force_join: "{{ ipaclient_force_join }}"
### additional ###
server: "{{ result_ipareplica_test.server }}"
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
config_ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
dirman_password: "{{ __derived_dirman_password }}"
setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
when: result_ipareplica_test.change_master_for_certmonger
- name: Install - Setup otpd
ipareplica_setup_otpd:
### server ###
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
no_ui_redirect: "{{ ipareplica_no_ui_redirect }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ __derived_dirman_password }}"
- name: Install - Setup custodia
ipareplica_setup_custodia:
### server ###
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
no_ui_redirect: "{{ ipareplica_no_ui_redirect }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
config_master_host_name:
"{{ result_ipareplica_prepare.config_master_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
_kra_host_name: "{{ result_ipareplica_prepare.config_kra_host_name }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ __derived_dirman_password }}"
- name: Install - Setup CA
ipareplica_setup_ca:
### server ###
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
pki_config_override:
"{{ ipareplica_pki_config_override | default(omit) }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
_kra_host_name: "{{ result_ipareplica_prepare.config_kra_host_name }}"
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_random_serial_numbers: "{{ result_ipareplica_prepare._random_serial_numbers }}"
dirman_password: "{{ __derived_dirman_password }}"
config_setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
config_ca_host_name:
"{{ result_ipareplica_install_ca_certs.config_ca_host_name }}"
config_ips: "{{ result_ipareplica_prepare.config_ips }}"
when: result_ipareplica_prepare._ca_enabled
- name: Install - KRB enable SSL
ipareplica_krb_enable_ssl:
### server ###
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ __derived_dirman_password }}"
- name: Install - DS apply updates
ipareplica_ds_apply_updates:
### server ###
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
no_ui_redirect: "{{ ipareplica_no_ui_redirect }}"
dirsrv_config_file: "{{ ipareplica_dirsrv_config_file | default(omit) }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info if result_ipareplica_prepare._pkinit_pkcs12_info != None else omit }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ __derived_dirman_password }}"
ds_ca_subject: "{{ result_ipareplica_setup_ds.ds_ca_subject }}"
- name: Install - Setup kra
ipareplica_setup_kra:
### basic ###
dm_password: "{{ ipadm_password | default(omit) }}"
password: "{{ ipaadmin_password | default(omit) }}"
ip_addresses: "{{ ipareplica_ip_addresses | default([]) }}"
domain: "{{ result_ipareplica_test.domain }}"
realm: "{{ result_ipareplica_test.realm }}"
hostname: "{{ result_ipareplica_test.hostname }}"
ca_cert_files: "{{ ipareplica_ca_cert_files | default([]) }}"
no_host_dns: "{{ ipareplica_no_host_dns }}"
pki_config_override:
"{{ ipareplica_pki_config_override | default(omit) }}"
### replica ###
setup_adtrust: "{{ result_ipareplica_test.setup_adtrust }}"
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
setup_dns: "{{ ipareplica_setup_dns }}"
### ssl certificate ###
dirsrv_cert_files: "{{ ipareplica_dirsrv_cert_files | default([]) }}"
### client ###
force_join: "{{ ipaclient_force_join }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
server: "{{ result_ipareplica_test.server }}"
config_master_host_name:
"{{ result_ipareplica_prepare.config_master_host_name }}"
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
_kra_host_name: "{{ result_ipareplica_prepare.config_kra_host_name }}"
_ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
dirman_password: "{{ __derived_dirman_password }}"
when: result_ipareplica_test.setup_kra
- name: Install - Restart KDC
ipareplica_restart_kdc:
### server ###
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
no_ui_redirect: "{{ ipareplica_no_ui_redirect }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ __derived_dirman_password }}"
- name: Install - Custodia import dm password
ipareplica_custodia_import_dm_password:
### server ###
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
no_ui_redirect: "{{ ipareplica_no_ui_redirect }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
config_master_host_name:
"{{ result_ipareplica_prepare.config_master_host_name }}"
config_ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
_kra_host_name: "{{ result_ipareplica_prepare.config_kra_host_name }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ __derived_dirman_password }}"
config_setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
- name: Install - Promote SSSD
ipareplica_promote_sssd:
### replica ###
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
ccache: "{{ result_ipareplica_prepare.ccache }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
config_setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
config_master_host_name:
"{{ result_ipareplica_prepare.config_master_host_name }}"
- name: Install - Promote openldap.conf
ipareplica_promote_openldap_conf:
### replica ###
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
ccache: "{{ result_ipareplica_prepare.ccache }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
config_setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
config_master_host_name:
"{{ result_ipareplica_prepare.config_master_host_name }}"
- name: Install - Setup DNS
ipareplica_setup_dns:
### server ###
setup_dns: "{{ ipareplica_setup_dns }}"
### replica ###
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### dns ###
zonemgr: "{{ ipareplica_zonemgr | default(omit) }}"
forwarders: "{{ ipareplica_forwarders | default([]) }}"
forward_policy: "{{ result_ipareplica_prepare.forward_policy if
result_ipareplica_prepare.forward_policy is
not none else omit }}"
no_dnssec_validation: "{{ ipareplica_no_dnssec_validation }}"
### additional ###
dns_ip_addresses: "{{ result_ipareplica_prepare.dns_ip_addresses }}"
dns_reverse_zones: "{{ result_ipareplica_prepare.dns_reverse_zones }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
config_master_host_name:
"{{ result_ipareplica_prepare.config_master_host_name }}"
- name: Install - Setup adtrust
ipareplica_setup_adtrust:
### replica ###
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### ad trust ###
enable_compat: "{{ ipareplica_enable_compat }}"
rid_base: "{{ result_ipareplica_prepare.rid_base }}"
secondary_rid_base: "{{ result_ipareplica_prepare.secondary_rid_base }}"
### additional ###
ccache: "{{ result_ipareplica_prepare.ccache }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
setup_adtrust: "{{ result_ipareplica_test.setup_adtrust }}"
config_master_host_name:
"{{ result_ipareplica_prepare.config_master_host_name }}"
adtrust_netbios_name:
"{{ result_ipareplica_prepare.adtrust_netbios_name }}"
adtrust_reset_netbios_name:
"{{ result_ipareplica_prepare.adtrust_reset_netbios_name }}"
when: result_ipareplica_test.setup_adtrust or
result_ipareplica_test.sid_generation_always
- name: Install - Enable IPA
ipareplica_enable_ipa:
hostname: "{{ result_ipareplica_test.hostname }}"
hidden_replica: "{{ ipareplica_hidden_replica }}"
### server ###
### replica ###
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
ccache: "{{ result_ipareplica_prepare.ccache }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
config_master_host_name:
"{{ result_ipareplica_prepare.config_master_host_name }}"
register: result_ipareplica_enable_ipa
always:
- name: Install - Cleanup root IPA cache
ansible.builtin.file:
path: "/root/.ipa_cache"
state: absent
- name: Cleanup temporary files
ansible.builtin.file:
path: "{{ item }}"
state: absent
with_items:
- "/etc/ipa/.tmp_pkcs12_dirsrv"
- "/etc/ipa/.tmp_pkcs12_http"
- "/etc/ipa/.tmp_pkcs12_pkinit"
ansible-freeipa-master/roles/ipareplica/tasks/main.yml 0000664 0000000 0000000 00000002276 14600563364 0023444 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipareplica
- name: Import variables specific to distribution
ansible.builtin.include_vars: "{{ item }}"
with_first_found:
- "vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_version'] }}.yml"
- "vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "vars/{{ ansible_facts['distribution'] }}.yml"
# os_family is used as a fallback for distros which are not currently
# supported, but are based on a supported distro family. For example,
# Oracle, Rocky, Alma and Alibaba linux, which are all "RedHat" based.
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_version'] }}.yml"
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "vars/{{ ansible_facts['os_family'] }}.yml"
# If neither distro nor family is supported, try a default configuration.
- "vars/default.yml"
- name: Install IPA replica
ansible.builtin.include_tasks: install.yml
when: state|default('present') == 'present'
- name: Uninstall IPA replica
ansible.builtin.include_tasks: uninstall.yml
when: state|default('present') == 'absent'
ansible-freeipa-master/roles/ipareplica/tasks/uninstall.yml 0000664 0000000 0000000 00000002010 14600563364 0024513 0 ustar 00root root 0000000 0000000 ---
# tasks to uninstall IPA replica
- name: Set parameters
ansible.builtin.set_fact:
_ignore_topology_disconnect: "{{ ipaserver_ignore_topology_disconnect | default(ipareplica_ignore_topology_disconnect) | default(omit) }}"
_ignore_last_of_role: "{{ ipaserver_ignore_last_of_role | default(ipareplica_ignore_last_of_role) | default(omit) }}"
_remove_from_domain: "{{ ipaserver_remove_from_domain | default(ipareplica_remove_from_domain) | default(omit) }}"
_remove_on_server: "{{ ipaserver_remove_on_server | default(ipareplica_remove_on_server) | default(omit) }}"
- name: Uninstall - Uninstall replica
ansible.builtin.include_role:
name: ipaserver
vars:
state: absent
ipaserver_ignore_topology_disconnect: "{{ _ignore_topology_disconnect | default(false) }}"
ipaserver_ignore_last_of_role: "{{ _ignore_last_of_role | default(false) }}"
ipaserver_remove_from_domain: "{{ _remove_from_domain | default(false) }}"
ipaserver_remove_on_server: "{{ _remove_on_server | default(NULL) }}"
ansible-freeipa-master/roles/ipareplica/vars/ 0000775 0000000 0000000 00000000000 14600563364 0021614 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipareplica/vars/Fedora-25.yml 0000664 0000000 0000000 00000000407 14600563364 0023764 0 ustar 00root root 0000000 0000000 # defaults file for ipareplica
# vars/Fedora-25.yml
---
ipareplica_packages: [ "ipa-server", "libselinux-python" ]
ipareplica_packages_dns: [ "ipa-server-dns" ]
ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ]
ipareplica_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipareplica/vars/Fedora-26.yml 0000664 0000000 0000000 00000000407 14600563364 0023765 0 ustar 00root root 0000000 0000000 # defaults file for ipareplica
# vars/Fedora-26.yml
---
ipareplica_packages: [ "ipa-server", "libselinux-python" ]
ipareplica_packages_dns: [ "ipa-server-dns" ]
ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ]
ipareplica_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipareplica/vars/Fedora-27.yml 0000664 0000000 0000000 00000000407 14600563364 0023766 0 ustar 00root root 0000000 0000000 # defaults file for ipareplica
# vars/Fedora-27.yml
---
ipareplica_packages: [ "ipa-server", "libselinux-python" ]
ipareplica_packages_dns: [ "ipa-server-dns" ]
ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ]
ipareplica_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipareplica/vars/Fedora.yml 0000664 0000000 0000000 00000000421 14600563364 0023534 0 ustar 00root root 0000000 0000000 # defaults file for ipareplica
# vars/Fedora.yml
---
ipareplica_packages: [ "freeipa-server", "python3-libselinux" ]
ipareplica_packages_dns: [ "freeipa-server-dns" ]
ipareplica_packages_adtrust: [ "freeipa-server-trust-ad" ]
ipareplica_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipareplica/vars/RedHat-7.yml 0000664 0000000 0000000 00000000406 14600563364 0023652 0 ustar 00root root 0000000 0000000 # defaults file for ipareplica
# vars/RedHat-7.yml
---
ipareplica_packages: [ "ipa-server", "libselinux-python" ]
ipareplica_packages_dns: [ "ipa-server-dns" ]
ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ]
ipareplica_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipareplica/vars/RedHat-8.yml 0000664 0000000 0000000 00000000361 14600563364 0023653 0 ustar 00root root 0000000 0000000 # defaults file for ipareplica
# vars/RedHat-8.yml
---
ipareplica_packages: [ "@idm:DL1/server" ]
ipareplica_packages_dns: [ "@idm:DL1/dns" ]
ipareplica_packages_adtrust: [ "@idm:DL1/adtrust" ]
ipareplica_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipareplica/vars/Ubuntu-18.04.yml 0000664 0000000 0000000 00000000700 14600563364 0024266 0 ustar 00root root 0000000 0000000 # vars/Ubuntu.yml
---
ipareplica_packages: [ "freeipa-server" ]
ipareplica_packages_dns: [ "freeipa-server-dns" ]
ipareplica_packages_adtrust: [ "freeipa-server-trust-ad" ]
ipareplica_packages_firewalld: [ "firewalld" ]
# Ubuntu Bionic Beaver must use python2 as Python interpreter due
# to the way python-ipalib package is defined.
# Package python2.7 must be installed before executing this role.
ansible_python_interpreter: '/usr/bin/python2.7'
ansible-freeipa-master/roles/ipareplica/vars/Ubuntu.yml 0000664 0000000 0000000 00000000373 14600563364 0023624 0 ustar 00root root 0000000 0000000 # defaults file for ipareplica
# vars/Ubuntu.yml
---
ipareplica_packages: [ "freeipa-server" ]
ipareplica_packages_dns: [ "freeipa-server-dns" ]
ipareplica_packages_adtrust: [ "freeipa-server-trust-ad" ]
ipareplica_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipareplica/vars/default.yml 0000664 0000000 0000000 00000000422 14600563364 0023761 0 ustar 00root root 0000000 0000000 # defaults file for ipareplica
# vars/default.yml
---
ipareplica_packages: [ "freeipa-server", "python3-libselinux" ]
ipareplica_packages_dns: [ "freeipa-server-dns" ]
ipareplica_packages_adtrust: [ "freeipa-server-trust-ad" ]
ipareplica_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipaserver/ 0000775 0000000 0000000 00000000000 14600563364 0020530 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaserver/README.md 0000664 0000000 0000000 00000037402 14600563364 0022015 0 ustar 00root root 0000000 0000000 ipaserver role
==============
Description
-----------
This role allows to configure and IPA server.
**Note**: The ansible playbooks and role require a configured ansible environment where the ansible nodes are reachable and are properly set up to have an IP address and a working package manager.
Features
--------
* Server deployment
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.5 and up are supported by the server role.
Supported Distributions
-----------------------
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
* Ubuntu 16.04 and 18.04
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
* Supported distribution (needed for package installation only, see above)
Limitations
-----------
**External signed CA**
External signed CA is now supported. But the currently needed two step process is an issue for the processing in a simple playbook.
Work is planned to have a new method to handle CSR for external signed CAs in a separate step before starting the server installation.
Usage
=====
Example inventory file with fixed domain and realm, setting up of the DNS server and using forwarders from /etc/resolv.conf:
```ini
[ipaserver]
ipaserver2.example.com
[ipaserver:vars]
ipaserver_domain=example.com
ipaserver_realm=EXAMPLE.COM
ipaserver_setup_dns=yes
ipaserver_auto_forwarders=yes
```
Example playbook to setup the IPA server using admin and dirman passwords from an [Ansible Vault](http://docs.ansible.com/ansible/latest/playbooks_vault.html) file:
```yaml
---
- name: Playbook to configure IPA server
hosts: ipaserver
become: true
vars_files:
- playbook_sensitive_data.yml
roles:
- role: ipaserver
state: present
```
Example playbook to unconfigure the IPA server using principal and password from inventory file:
```yaml
---
- name: Playbook to unconfigure IPA server
hosts: ipaserver
become: true
roles:
- role: ipaserver
state: absent
```
Example inventory file with fixed domain, realm, admin and dirman passwords:
```ini
[ipaserver]
ipaserver.example.com
[ipaserver:vars]
ipaserver_domain=example.com
ipaserver_realm=EXAMPLE.COM
ipaadmin_password=MySecretPassword123
ipadm_password=MySecretPassword234
```
Example playbook to setup the IPA server using admin and dirman passwords from inventory file:
```yaml
---
- name: Playbook to configure IPA server
hosts: ipaserver
become: true
roles:
- role: ipaserver
state: present
```
Example playbook to setup the IPA primary with external signed CA using the previous inventory file:
Server installation step 1: Generate CSR, copy to controller as `-ipa.csr`
```yaml
---
- name: Playbook to configure IPA server step1
hosts: ipaserver
become: true
vars:
ipaserver_external_ca: yes
roles:
- role: ipaserver
state: present
post_tasks:
- name: Copy CSR /root/ipa.csr from node to "{{ groups.ipaserver[0] + '-ipa.csr' }}"
fetch:
src: /root/ipa.csr
dest: "{{ groups.ipaserver[0] + '-ipa.csr' }}"
flat: yes
```
Sign with CA: This is up to you
Server installation step 2: Copy `-chain.crt` to the IPA server and continue with installation of the primary.
```yaml
---
- name: Playbook to configure IPA server step3
hosts: ipaserver
become: true
vars:
ipaserver_external_cert_files: "/root/chain.crt"
pre_tasks:
- name: Copy "{{ groups.ipaserver[0] + '-chain.crt' }}" to /root/chain.crt on node
copy:
src: "{{ groups.ipaserver[0] + '-chain.crt' }}"
dest: "/root/chain.crt"
force: yes
roles:
- role: ipaserver
state: present
```
The files can also be copied automatically: Set `ipaserver_copy_csr_to_controller` to true in the server installation step 1 and set `ipaserver_external_cert_files_from_controller` to point to the `chain.crt` file in the server installation step 2.
Since version 4.10, FreeIPA supports creating certificates using random serial numbers. Random serial numbers is a global and permanent setting, that can only be activated while deploying the first server of the domain. Replicas will inherit this setting automatically. An example of an inventory file to deploy a server with random serial numbers enabled is:
```ini
[ipaserver]
ipaserver.example.com
[ipaserver:vars]
ipaserver_domain=example.com
ipaserver_realm=EXAMPLE.COM
ipaadmin_password=MySecretPassword123
ipadm_password=MySecretPassword234
ipaserver_random_serial_numbers=true
```
By setting the variable in the inventory file, the same ipaserver deployment playbook, shown before, can be used.
Example inventory file to remove a server from the domain:
```ini
[ipaserver]
ipaserver.example.com
[ipaserver:vars]
ipaadmin_password=MySecretPassword123
ipaserver_remove_from_domain=true
```
Example playbook to remove an IPA server using admin passwords from the domain:
```yaml
---
- name: Playbook to remove IPA server
hosts: ipaserver
become: true
roles:
- role: ipaserver
state: absent
```
The inventory will enable the removal of the server (also a replica) from the domain. Additional options are needed if the removal of the server/replica is resulting in a topology disconnect or if the server/replica is the last that has a role.
To continue with the removal with a topology disconnect it is needed to set these parameters:
```ini
ipaserver_ignore_topology_disconnect=true
ipaserver_remove_on_server=ipaserver2.example.com
```
To continue with the removal for a server that is the last that has a role:
```ini
ipaserver_ignore_last_of_role=true
```
Be careful with enabling the `ipaserver_ignore_topology_disconnect` and especially `ipaserver_ignore_last_of_role`, the change can not be reverted easily.
Playbooks
=========
The playbooks needed to deploy or undeploy a server are part of the repository in the playbooks folder. There are also playbooks to deploy and undeploy clusters.
```
install-server.yml
uninstall-server.yml
```
Please remember to link or copy the playbooks to the base directory of ansible-freeipa if you want to use the roles within the source archive.
How to setup a server
---------------------
```bash
ansible-playbook -v -i inventory/hosts install-server.yml
```
This will deploy the server defined in the inventory file.
Variables
=========
Base Variables
--------------
Variable | Description | Required
-------- | ----------- | --------
`ipaserver` | This group with the single IPA server full qualified hostname. (list of strings) | yes
`ipadm_password` | The password for the Directory Manager. (string) | no
`ipaadmin_password` | The password for the IPA admin user (string) | no
`ipaserver_ip_addresses` | The list of master server IP addresses. (list of strings) | no
`ipaserver_domain` | The primary DNS domain of an existing IPA deployment. (string) | no
`ipaserver_realm` | The Kerberos realm of an existing IPA deployment. (string) | no
`ipaserver_hostname` | Fully qualified name of the server. (string) | no
`ipaserver_no_host_dns` | Do not use DNS for hostname lookup during installation. (bool, default: false) | no
`ipaserver_mem_check` | Checking for minimum required memory for the deployment. This is only usable with recent FreeIPA versions (4.8.10+) else ignored. (bool, default: yes) | no
Server Variables
----------------
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_setup_adtrust` | Configure AD Trust capability. (bool, default: false) | no
`ipaserver_setup_kra` | Install and configure a KRA on this server. (bool, default: false) | no
`ipaserver_setup_dns` | Configure an integrated DNS server, create DNS zone specified by domain. (bool, default: false) | no
`ipaserver_idstart` | The starting user and group id number. (integer, default: random) | no
`ipaserver_idmax` | The maximum user and group id number. (integer, default: idstart+199999) | no
`ipaserver_no_hbac_allow` | Do not install allow_all HBAC rule. (bool) | no
`ipaserver_no_ui_redirect` | Do not automatically redirect to the Web UI. (bool) | no
`ipaserver_dirsrv_config_file` | The path to LDIF file that will be used to modify configuration of dse.ldif during installation. (string) | no
`ipaserver_pki_config_override` | Path to ini file with config overrides. This is only usable with recent FreeIPA versions. (string) | no
`ipaserver_random_serial_numbers` | Enable use of random serial numbers for certificates. Requires FreeIPA version 4.10 or later. (boolean) | no
SSL certificate Variables
-------------------------
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_dirsrv_cert_files` | Files containing the Directory Server SSL certificate and private keys. (list of strings) | no
`ipaserver_http_cert_files` | File containing the Apache Server SSL certificate and private key. (list of string) | no
`ipaserver_pkinit_cert_files` | File containing the Kerberos KDC SSL certificate and private key. (list of string) | no
`ipaserver_dirsrv_pin` | The password to unlock the Directory Server private key. (string) | no
`ipaserver_http_pin` | The password to unlock the Apache Server private key. (string) | no
`ipaserver_pkinit_pin` | The password to unlock the Kerberos KDC private key. (string) | no
`ipaserver_dirsrv_cert_name` | Name of the Directory Server SSL certificate to install. (string) | no
`ipaserver_http_cert_name` | Name of the Apache Server SSL certificate to install. (string) | no
`ipaserver_pkinit_cert_name` | Name of the Kerberos KDC SSL certificate to install. (string) | no
`ipaserver_no_pkinit` | Disable pkinit setup steps (boolean) | no
NOTE: If one of the `ipaserver_http_cert_files` or `ipaserver_pkinit_cert_files` is specified, then both are required, so declaring only one of them will raise an error. Additionally, one of `ipaserver_pkinit_cert_files` or `ipaserver_no_pkinit` must be provided as well.
Client Variables
----------------
Variable | Description | Required
-------- | ----------- | --------
`ipaclient_ntp_servers` | The list defines the NTP servers to be used. | no
`ipaclient_ntp_pool` | The string value defines the ntp server pool to be used. | no
`ipaclient_no_ntp` | The bool value defines if NTP will not be configured and enabled. `ipaclient_no_ntp` defaults to `no`. | no
`ipaclient_ssh_trust_dns` | The bool value defines if OpenSSH client will be configured to trust DNS SSHFP records. `ipaclient_ssh_trust_dns` defaults to `no`. | no
`ipaclient_no_ssh` | The bool value defines if OpenSSH client will be configured. `ipaclient_no_ssh` defaults to `no`. | no
`ipaclient_no_sshd` | The bool value defines if OpenSSH server will be configured. `ipaclient_no_sshd` defaults to `no`. | no
`ipaclient_no_sudo` | The bool value defines if SSSD will be configured as a data source for sudo. `ipaclient_no_sudo` defaults to `no`. | no
`ipaclient_subid` | The bool value defines if SSSD will be configured as a data source for subid. `ipaclient_subid` defaults to `no`. | no
`ipaclient_no_dns_sshfp` | The bool value defines if DNS SSHFP records will not be created automatically. `ipaclient_no_dns_sshfp` defaults to `no`. | no
Certificate system Variables
----------------------------
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_external_ca` | Generate a CSR for the IPA CA certificate to be signed by an external CA. (bool, default: false) | no
`ipaserver_external_ca_type` | Type of the external CA. (choice: generic, ms-cs) | no
`ipaserver_external_ca_profile` | Specify the certificate profile/template to use at the external CA. (string) | no
`ipaserver_external_cert_files` | Files containing the IPA CA certificates and the external CA certificate chains (list of string) | no
`ipaserver_subject_base` | The certificate subject base (default O=). RDNs are in LDAP order (most specific RDN first). (string) | no
`ipaserver_ca_subject` | The CA certificate subject DN (default CN=Certificate Authority,O=). RDNs are in LDAP order (most specific RDN first). (string) | no
`ipaserver_ca_signing_algorithm` | Signing algorithm of the IPA CA certificate. (choice: SHA1withRSA, SHA256withRSA, SHA512withRSA) | no
DNS Variables
-------------
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_allow_zone_overlap` | Allow creation of (reverse) zone even if the zone is already resolvable. (bool, default: false) | no
`ipaserver_reverse_zones` | The reverse DNS zones to use. (list of strings) | no
`ipaserver_no_reverse` | Do not create reverse DNS zone. (bool, default: false) | no
`ipaserver_auto_reverse` | Try to resolve reverse records and reverse zones for server IP addresses. (bool, default: false) | no
`ipaserver_zonemgr` | The e-mail address of the DNS zone manager. (string, default: hostmaster@DOMAIN.) | no
`ipaserver_forwarders` | Add DNS forwarders to the DNS configuration. (list of strings) | no
`ipaserver_no_forwarders` | Do not add any DNS forwarders. Root DNS servers will be used instead. (bool, default: false) | no
`ipaserver_auto_forwarders` | Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS. (bool, default: false) | no
`ipaserver_forward_policy` | DNS forwarding policy for global forwarders specified using other options. (choice: first, only) | no
`ipaserver_no_dnssec_validation` | Disable DNSSEC validation on this server. (bool, default: false) | no
AD trust Variables
------------------
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_enable_compat`| Enables support for trusted domains users for old clients through Schema Compatibility plugin. (bool, default: false) | no
`ipaserver_netbios_name` | The NetBIOS name for the IPA domain. (string) | no
`ipaserver_rid_base` | First RID value of the local domain. (integer) | no
`ipaserver_secondary_rid_base` | Start value of the secondary RID range. (integer) | no
Special Variables
-----------------
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_install_packages` | The bool value defines if the needed packages are installed on the node. (bool, default: true) | no
`ipaserver_setup_firewalld` | The value defines if the needed services will automatically be opened in the firewall managed by firewalld. (bool, default: true) | no
`ipaserver_firewalld_zone` | The value defines the firewall zone that will be used. This needs to be an existing runtime and permanent zone. (string) | no
`ipaserver_external_cert_files_from_controller` | Files containing the IPA CA certificates and the external CA certificate chains on the controller that will be copied to the ipaserver host to `/root` folder. (list of string) | no
`ipaserver_copy_csr_to_controller` | Copy the generated CSR from the ipaserver to the controller as `"{{ inventory_hostname }}-ipa.csr"`. (bool) | no
Undeploy Variables (`state`: absent)
------------------------------------
These settings should only be used if the result is really wanted. The change might not be revertable easily.
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_ignore_topology_disconnect` | If enabled this enforces the removal of the server even if it results in a topology disconnect. Be careful with this setting. (bool) | false
`ipaserver_ignore_last_of_role` | If enabled this enforces the removal of the server even if the server is the last with one that has a role. Be careful, this might not be revered easily. (bool) | false
`ipaserver_remove_from_domain` | This enables the removal of the server from the domain additionally to the undeployment. (bool) | false
`ipaserver_remove_on_server` | The value defines the server/replica in the domain that will to be used to remove the server/replica from the domain if `ipaserver_ignore_topology_disconnect` and `ipaserver_remove_from_domain` are enabled. Without the need to enable `ipaserver_ignore_topology_disconnect`, the value will be automatically detected using the replication agreements of the server/replica. (string) | false
Authors
=======
Thomas Woerner
ansible-freeipa-master/roles/ipaserver/defaults/ 0000775 0000000 0000000 00000000000 14600563364 0022337 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaserver/defaults/main.yml 0000664 0000000 0000000 00000002106 14600563364 0024005 0 ustar 00root root 0000000 0000000 ---
# defaults file for ipaserver
### basic ###
ipaserver_no_host_dns: no
### server ###
ipaserver_setup_adtrust: no
ipaserver_setup_kra: no
ipaserver_setup_dns: no
ipaserver_no_hbac_allow: no
ipaserver_no_pkinit: no
ipaserver_no_ui_redirect: no
ipaserver_mem_check: yes
ipaserver_random_serial_numbers: false
### ssl certificate ###
### client ###
ipaclient_mkhomedir: no
ipaclient_no_ntp: no
#ipaclient_ssh_trust_dns: no
#ipaclient_no_ssh: no
#ipaclient_no_sshd: no
#ipaclient_no_dns_sshfp: no
### certificate system ###
ipaserver_external_ca: no
### dns ###
ipaserver_allow_zone_overlap: no
ipaserver_no_reverse: no
ipaserver_auto_reverse: no
ipaserver_no_forwarders: no
ipaserver_auto_forwarders: no
ipaserver_no_dnssec_validation: no
### ad trust ###
ipaserver_enable_compat: no
ipaserver_setup_ca: yes
### packages ###
ipaserver_install_packages: yes
### firewalld ###
ipaserver_setup_firewalld: yes
### additional ###
ipaserver_copy_csr_to_controller: no
### uninstall ###
ipaserver_ignore_topology_disconnect: no
ipaserver_ignore_last_of_role: no
ipaserver_remove_from_domain: false
ansible-freeipa-master/roles/ipaserver/library/ 0000775 0000000 0000000 00000000000 14600563364 0022174 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaserver/library/ipaserver_enable_ipa.py 0000664 0000000 0000000 00000007521 14600563364 0026712 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-server-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_enable_ipa
short_description: Enable IPA
description: Enable IPA
options:
hostname:
description: Fully qualified name of this host
type: str
required: no
setup_dns:
description: Configure bind with our zone
type: bool
required: yes
setup_ca:
description: Configure a dogtag CA
type: bool
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports,
AnsibleModuleLog, setup_logging, options, paths, api, sysrestore, tasks,
service, bindinstance, redirect_stdout, services
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
hostname=dict(required=False, type='str'),
setup_dns=dict(required=True, type='bool'),
setup_ca=dict(required=True, type='bool'),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# set values #############################################################
options.host_name = ansible_module.params.get('hostname')
options.setup_dns = ansible_module.params.get('setup_dns')
options.setup_ca = ansible_module.params.get('setup_ca')
# Configuration for ipalib, we will bootstrap and finalize later, after
# we are sure we have the configuration file ready.
cfg = dict(
context='installer',
confdir=paths.ETC_IPA,
in_server=True,
# make sure host name specified by user is used instead of default
host=options.host_name,
)
if options.setup_ca:
# we have an IPA-integrated CA
cfg['ca_host'] = options.host_name
api.bootstrap(**cfg)
api.finalize()
api.Backend.ldap2.connect()
# setup ds ######################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
if hasattr(tasks, "configure_tmpfiles"):
# Make sure the files we crated in /var/run are recreated at startup
tasks.configure_tmpfiles()
if hasattr(service, "enable_services"):
# Enable configured services and update DNS SRV records
service.enable_services(options.host_name)
api.Command.dns_update_system_records()
if not options.setup_dns:
# After DNS and AD trust are configured and services are
# enabled, create a dummy instance to dump DNS configuration.
bind = bindinstance.BindInstance(fstore)
bind.create_file_with_system_records()
with redirect_stdout(ansible_log):
services.knownservices.ipa.enable()
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_get_connected_server.py 0000664 0000000 0000000 00000016660 14600563364 0031026 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaserver_get_connected_server
short_description: Get connected servers for server
description: Get connected servers for server
options:
ipaadmin_principal:
description: The admin principal.
default: admin
type: str
ipaadmin_password:
description: The admin password.
required: true
type: str
hostname:
description: The FQDN server name.
type: str
required: true
author:
- Thomas Woerner (@t-woerner)
"""
EXAMPLES = """
"""
RETURN = """
server:
description: Connected server name
returned: always
type: str
"""
import os
import tempfile
import shutil
from contextlib import contextmanager
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils import six
try:
from ipalib import api
from ipalib import errors as ipalib_errors # noqa
from ipalib.config import Env
from ipaplatform.paths import paths
from ipapython.ipautil import run
from ipalib.constants import DEFAULT_CONFIG
try:
from ipalib.install.kinit import kinit_password
except ImportError:
from ipapython.ipautil import kinit_password
except ImportError as _err:
MODULE_IMPORT_ERROR = str(_err)
else:
MODULE_IMPORT_ERROR = None
if six.PY3:
unicode = str
def temp_kinit(principal, password):
"""Kinit with password using a temporary ccache."""
ccache_dir = tempfile.mkdtemp(prefix='krbcc')
ccache_name = os.path.join(ccache_dir, 'ccache')
try:
kinit_password(principal, password, ccache_name)
except RuntimeError as e:
raise RuntimeError("Kerberos authentication failed: %s" % str(e))
os.environ["KRB5CCNAME"] = ccache_name
return ccache_dir, ccache_name
def temp_kdestroy(ccache_dir, ccache_name):
"""Destroy temporary ticket and remove temporary ccache."""
if ccache_name is not None:
run([paths.KDESTROY, '-c', ccache_name], raiseonerr=False)
os.environ.pop('KRB5CCNAME', None)
if ccache_dir is not None:
shutil.rmtree(ccache_dir, ignore_errors=True)
@contextmanager
def ipa_connect(module, principal=None, password=None):
"""
Create a context with a connection to IPA API.
Parameters
----------
module: AnsibleModule
The AnsibleModule to use
principal: string
The optional principal name
password: string
The admin password.
"""
if not password:
module.fail_json(msg="Password is required.")
if not principal:
principal = "admin"
ccache_dir = None
ccache_name = None
try:
ccache_dir, ccache_name = temp_kinit(principal, password)
# api_connect start
env = Env()
env._bootstrap()
env._finalize_core(**dict(DEFAULT_CONFIG))
api.bootstrap(context="server", debug=env.debug, log=None)
api.finalize()
if api.env.in_server:
backend = api.Backend.ldap2
else:
backend = api.Backend.rpcclient
if not backend.isconnected():
backend.connect(ccache=ccache_name)
# api_connect end
except Exception as e:
module.fail_json(msg=str(e))
else:
try:
yield ccache_name
except Exception as e:
module.fail_json(msg=str(e))
finally:
temp_kdestroy(ccache_dir, ccache_name)
def ipa_command(command, name, args):
"""
Execute an IPA API command with a required `name` argument.
Parameters
----------
command: string
The IPA API command to execute.
name: string
The name parameter to pass to the command.
args: dict
The parameters to pass to the command.
"""
return api.Command[command](name, **args)
def _afm_convert(value):
if value is not None:
if isinstance(value, list):
return [_afm_convert(x) for x in value]
if isinstance(value, dict):
return {_afm_convert(k): _afm_convert(v)
for k, v in value.items()}
if isinstance(value, str):
return to_text(value)
return value
def module_params_get(module, name):
return _afm_convert(module.params.get(name))
def host_show(module, name):
_args = {
"all": True,
}
try:
_result = ipa_command("host_show", name, _args)
except ipalib_errors.NotFound as e:
msg = str(e)
if "host not found" in msg:
return None
module.fail_json(msg="host_show failed: %s" % msg)
return _result["result"]
def main():
module = AnsibleModule(
argument_spec=dict(
ipaadmin_principal=dict(type="str", default="admin"),
ipaadmin_password=dict(type="str", required=True, no_log=True),
hostname=dict(type="str", required=True),
),
supports_check_mode=True,
)
if MODULE_IMPORT_ERROR is not None:
module.fail_json(msg=MODULE_IMPORT_ERROR)
# In check mode always return changed.
if module.check_mode:
module.exit_json(changed=False)
ipaadmin_principal = module_params_get(module, "ipaadmin_principal")
ipaadmin_password = module_params_get(module, "ipaadmin_password")
hostname = module_params_get(module, "hostname")
server = None
right_left = ["iparepltoposegmentrightnode", "iparepltoposegmentleftnode"]
with ipa_connect(module, ipaadmin_principal, ipaadmin_password):
# At first search in the domain, then ca suffix:
# Search for the first iparepltoposegmentleftnode (node 2), where
# iparepltoposegmentrightnode is hostname (node 1), then for the
# first iparepltoposegmentrightnode (node 2) where
# iparepltoposegmentleftnode is hostname (node 1).
for suffix_name in ["domain", "ca"]:
for node1, node2 in [[right_left[0], right_left[1]],
[right_left[1], right_left[0]]]:
args = {node1: hostname}
result = api.Command.topologysegment_find(
suffix_name, **args)
if result and "result" in result and len(result["result"]) > 0:
res = result["result"][0]
if node2 in res:
if len(res[node2]) > 0:
server = res[node2][0]
break
if server is not None:
module.exit_json(changed=False, server=server)
module.exit_json(changed=False)
if __name__ == "__main__":
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_load_cache.py 0000664 0000000 0000000 00000005574 14600563364 0026703 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_load_cache
short_description: Load cache file
description: Load cache file
options:
dm_password:
description: Directory Manager password
type: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports, setup_logging, options, paths, read_cache
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=True, type='str', no_log=True),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
# set values ############################################################
# basic
options.dm_password = ansible_module.params.get('dm_password')
# restore cache #########################################################
if os.path.isfile(paths.ROOT_IPA_CACHE):
if options.dm_password is None:
ansible_module.fail_json(msg="Directory Manager password required")
try:
cache_vars = read_cache(options.dm_password)
options.__dict__.update(cache_vars)
if cache_vars.get('external_ca', False):
options.external_ca = False
options.interactive = False
except Exception as e:
ansible_module.fail_json(
msg="Cannot process the cache file: %s" % str(e))
kwargs = {"changed": True}
for name in options.__dict__:
kwargs[name] = options.__dict__[name]
ansible_module.exit_json(**kwargs)
# done ##################################################################
ansible_module.exit_json(changed=False)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_master_password.py 0000664 0000000 0000000 00000005561 14600563364 0030052 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-server-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_master_password
short_description: Generate kerberos master password if not given
description:
Generate kerberos master password if not given
options:
dm_password:
description: Directory Manager password
type: str
required: yes
master_password:
description: kerberos master password (normally autogenerated)
type: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
password:
description: The master password
type: str
returned: always
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports,
setup_logging, options, paths, read_cache, ipa_generate_password
)
def main():
module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=True, type='str', no_log=True),
master_password=dict(required=False, type='str', no_log=True),
),
supports_check_mode=False,
)
module._ansible_debug = True
check_imports(module)
setup_logging()
options.dm_password = module.params.get('dm_password')
options.master_password = module.params.get('master_password')
# This will override any settings passed in on the cmdline
if os.path.isfile(paths.ROOT_IPA_CACHE):
# dm_password check removed, checked already
try:
cache_vars = read_cache(options.dm_password)
options.__dict__.update(cache_vars)
except Exception as e:
module.fail_json(msg="Cannot process the cache file: %s" % str(e))
if not options.master_password:
options.master_password = ipa_generate_password()
module.exit_json(changed=True,
password=options.master_password)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_prepare.py 0000664 0000000 0000000 00000043122 14600563364 0026266 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_prepare
short_description: Prepare IPA server deployment
description: Prepare IPA server deployment
options:
force:
description: Installer force parameter
type: bool
default: no
required: no
dm_password:
description: Directory Manager password
type: str
required: yes
password:
description: Admin user kerberos password
type: str
required: yes
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: no
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
type: list
elements: str
required: no
no_host_dns:
description: Do not use DNS for hostname lookup during installation
type: bool
default: no
required: no
setup_adtrust:
description: Configure AD trust capability
type: bool
default: no
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
default: no
required: no
setup_dns:
description: Configure bind with our zone
type: bool
default: no
required: no
external_ca:
description: External ca setting
type: bool
required: no
external_ca_type:
description: Type of the external CA
type: str
required: no
external_ca_profile:
description:
Specify the certificate profile/template to use at the external CA
type: str
required: no
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
type: list
elements: str
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: no
ca_subject:
description: The installer ca_subject setting
type: str
required: no
allow_zone_overlap:
description: Create DNS zone even if it already exists
type: bool
default: no
required: no
reverse_zones:
description: The reverse DNS zones to use
type: list
elements: str
required: no
no_reverse:
description: Do not create new reverse DNS zone
type: bool
default: no
required: no
auto_reverse:
description: Create necessary reverse zones
type: bool
default: no
required: no
forwarders:
description: Add DNS forwarders
type: list
elements: str
required: no
no_forwarders:
description: Do not add any DNS forwarders, use root servers instead
type: bool
default: no
required: no
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
type: bool
default: no
required: no
forward_policy:
description: DNS forwarding policy for global forwarders
type: str
choices: ['first', 'only']
required: no
no_dnssec_validation:
description: Disable DNSSEC validation
type: bool
default: no
required: no
enable_compat:
description: Enable support for trusted domains for old clients
type: bool
default: no
required: no
netbios_name:
description: NetBIOS name of the IPA domain
type: str
required: no
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
type: int
required: no
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
type: int
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
default: no
required: no
random_serial_numbers:
description: Enable random serial numbers
type: bool
default: no
required: no
sid_generation_always:
description: Enable SID generation always
type: bool
default: no
required: no
_hostname_overridden:
description: The installer _hostname_overridden setting
type: bool
default: no
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports, AnsibleModuleLog, setup_logging, options, sysrestore,
paths, ansible_module_get_parsed_ip_addresses,
redirect_stdout, adtrust, api, default_subject_base,
default_ca_subject_dn, ipautil, installutils, ca, kra, dns,
get_server_ip_address, no_matching_interface_for_ip_address_warning,
services, logger, tasks, update_hosts_file, ScriptError
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
force=dict(required=False, type='bool', default=False),
dm_password=dict(required=True, type='str', no_log=True),
password=dict(required=True, type='str', no_log=True),
ip_addresses=dict(required=False, type='list', elements='str',
default=[]),
domain=dict(required=True, type='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=False, type='str'),
ca_cert_files=dict(required=False, type='list', elements='str',
default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
# server
setup_adtrust=dict(required=False, type='bool', default=False),
setup_kra=dict(required=False, type='bool', default=False),
setup_dns=dict(required=False, type='bool', default=False),
# ssl certificate
# client
# certificate system
external_ca=dict(required=False, type='bool'),
external_ca_type=dict(required=False, type='str'),
external_ca_profile=dict(required=False, type='str'),
external_cert_files=dict(required=False, type='list',
elements='str', default=[]),
subject_base=dict(required=False, type='str'),
ca_subject=dict(required=False, type='str'),
# dns
allow_zone_overlap=dict(required=False, type='bool',
default=False),
reverse_zones=dict(required=False, type='list', elements='str',
default=[]),
no_reverse=dict(required=False, type='bool', default=False),
auto_reverse=dict(required=False, type='bool', default=False),
forwarders=dict(required=False, type='list', elements='str',
default=[]),
no_forwarders=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
forward_policy=dict(required=False, type='str',
choices=['first', 'only'], default=None),
no_dnssec_validation=dict(required=False, type='bool',
default=False),
# ad trust
enable_compat=dict(required=False, type='bool', default=False),
netbios_name=dict(required=False, type='str'),
rid_base=dict(required=False, type='int'),
secondary_rid_base=dict(required=False, type='int'),
# additional
setup_ca=dict(required=False, type='bool', default=False),
random_serial_numbers=dict(required=False, type='bool',
default=False),
sid_generation_always=dict(required=False, type='bool',
default=False),
_hostname_overridden=dict(required=False, type='bool',
default=False),
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# initialize return values for flake ############################
# These are set by ca.install_check and need to be passed to ca.install
# in the _setup_ca module and also some others.
options._subject_base = None
options._ca_subject = None
options._random_serial_numbers = False
# set values ####################################################
options.force = ansible_module.params.get('force')
options.dm_password = ansible_module.params.get('dm_password')
options.admin_password = ansible_module.params.get('password')
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.no_host_dns = ansible_module.params.get('no_host_dns')
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
# options.no_pkinit = ansible_module.params.get('no_pkinit')
# ssl certificate
# options.dirsrv_cert_files = ansible_module.params.get(
# 'dirsrv_cert_files')
# client
# options.no_ntp = ansible_module.params.get('no_ntp')
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_ca_type = ansible_module.params.get('external_ca_type')
options.external_ca_profile = ansible_module.params.get(
'external_ca_profile')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
options.ca_subject = ansible_module.params.get('ca_subject')
# dns
options.allow_zone_overlap = ansible_module.params.get(
'allow_zone_overlap')
options.reverse_zones = ansible_module.params.get('reverse_zones')
options.no_reverse = ansible_module.params.get('no_reverse')
options.auto_reverse = ansible_module.params.get('auto_reverse')
options.forwarders = ansible_module.params.get('forwarders')
options.no_forwarders = ansible_module.params.get('no_forwarders')
options.auto_forwarders = ansible_module.params.get('auto_forwarders')
options.forward_policy = ansible_module.params.get('forward_policy')
options.no_dnssec_validation = ansible_module.params.get(
'no_dnssec_validation')
# ad trust
options.enable_compat = ansible_module.params.get('enable_compat')
options.netbios_name = ansible_module.params.get('netbios_name')
# additional
options.setup_ca = ansible_module.params.get('setup_ca')
options.random_serial_numbers = ansible_module.params.get(
'random_serial_numbers')
options._host_name_overridden = ansible_module.params.get(
'_hostname_overridden')
sid_generation_always = ansible_module.params.get('sid_generation_always')
options.kasp_db_file = None
# init ##################################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
# subject_base
if not options.subject_base:
options.subject_base = str(default_subject_base(options.realm_name))
# set options.subject for old ipa releases
options.subject = options.subject_base
if not options.ca_subject:
options.ca_subject = str(default_ca_subject_dn(options.subject_base))
try:
# Configuration for ipalib, we will bootstrap and finalize later, after
# we are sure we have the configuration file ready.
cfg = dict(
context='installer',
confdir=paths.ETC_IPA,
in_server=True,
# make sure host name specified by user is used instead of default
host=options.host_name,
)
if options.setup_ca:
# we have an IPA-integrated CA
cfg['ca_host'] = options.host_name
# Create the management framework config file and finalize api
target_fname = paths.IPA_DEFAULT_CONF
# pylint: disable=invalid-name, consider-using-with
fd = open(target_fname, "w")
fd.write("[global]\n")
fd.write("host=%s\n" % options.host_name)
fd.write("basedn=%s\n" % ipautil.realm_to_suffix(options.realm_name))
fd.write("realm=%s\n" % options.realm_name)
fd.write("domain=%s\n" % options.domain_name)
fd.write("xmlrpc_uri=https://%s/ipa/xml\n" %
ipautil.format_netloc(options.host_name))
fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" %
installutils.realm_to_serverid(options.realm_name))
if options.setup_ca:
fd.write("enable_ra=True\n")
fd.write("ra_plugin=dogtag\n")
fd.write("dogtag_version=10\n")
else:
fd.write("enable_ra=False\n")
fd.write("ra_plugin=none\n")
fd.write("mode=production\n")
fd.close()
# pylint: enable=invalid-name, consider-using-with
# Must be readable for everyone
os.chmod(target_fname, 0o644)
api.bootstrap(**cfg)
api.finalize()
if options.setup_ca:
with redirect_stdout(ansible_log):
ca.install_check(False, None, options)
if options.setup_kra:
with redirect_stdout(ansible_log):
kra.install_check(api, None, options)
if options.setup_dns:
with redirect_stdout(ansible_log):
dns.install_check(False, api, False, options,
options.host_name)
ip_addresses = dns.ip_addresses
else:
ip_addresses = get_server_ip_address(options.host_name,
not options.interactive,
False,
options.ip_addresses)
# check addresses here, dns module is doing own check
no_matching_interface_for_ip_address_warning(ip_addresses)
options.ip_addresses = ip_addresses
options.reverse_zones = dns.reverse_zones
instance_name = "-".join(options.realm_name.split("."))
dirsrv = services.knownservices.dirsrv
if options.external_cert_files \
and dirsrv.is_installed(instance_name) \
and not dirsrv.is_running(instance_name):
logger.debug('Starting Directory Server')
services.knownservices.dirsrv.start(instance_name)
if options.setup_adtrust or sid_generation_always:
with redirect_stdout(ansible_log):
adtrust.install_check(False, options, api)
_update_hosts_file = False
# options needs to update hosts file when DNS subsystem will be
# installed or custom addresses are used
if options.ip_addresses or options.setup_dns:
_update_hosts_file = True
if options._host_name_overridden:
tasks.backup_hostname(fstore, sstore)
tasks.set_hostname(options.host_name)
if _update_hosts_file:
update_hosts_file(ip_addresses, options.host_name, fstore)
if hasattr(tasks, "configure_pkcs11_modules"):
if tasks.configure_pkcs11_modules(fstore):
ansible_log.info("Disabled p11-kit-proxy")
except (RuntimeError, ValueError, ScriptError,
ipautil.CalledProcessError) as err:
ansible_module.fail_json(msg=str(err))
ansible_module.exit_json(
changed=True,
# basic
ip_addresses=[str(ip) for ip in ip_addresses],
# certificate system
subject_base=options.subject_base,
_subject_base=options._subject_base,
ca_subject=options.ca_subject,
_ca_subject=options._ca_subject,
_random_serial_numbers=options._random_serial_numbers,
# dns
reverse_zones=options.reverse_zones,
forward_policy=options.forward_policy,
forwarders=options.forwarders,
no_dnssec_validation=options.no_dnssec_validation,
# additional
dns_ip_addresses=[str(ip) for ip
in dns.ip_addresses],
dns_reverse_zones=dns.reverse_zones,
adtrust_netbios_name=adtrust.netbios_name,
adtrust_reset_netbios_name=adtrust.reset_netbios_name)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_set_ds_password.py 0000664 0000000 0000000 00000017716 14600563364 0030045 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_set_ds_password
short_description: Set DS password
description: Set DS password
options:
dm_password:
description: Directory Manager password
type: str
required: yes
password:
description: Admin user kerberos password
type: str
required: yes
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: yes
setup_ca:
description: Configure a dogtag CA
type: bool
required: yes
idstart:
description: The starting value for the IDs range (default random)
type: int
required: yes
idmax:
description: The max value for the IDs range (default idstart+199999)
type: int
required: yes
no_hbac_allow:
description: Don't install allow_all HBAC rule
type: bool
default: no
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
default: no
required: no
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
type: str
required: no
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
type: list
elements: str
required: no
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
type: list
elements: str
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: no
ca_subject:
description: The installer ca_subject setting
type: str
required: no
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
type: list
elements: str
required: no
domainlevel:
description: The domain level
type: int
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports,
MAX_DOMAIN_LEVEL, AnsibleModuleLog, options, sysrestore, paths,
api_Backend_ldap2, ds_init_info, redirect_stdout, setup_logging,
krbinstance, service
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=True, type='str', no_log=True),
password=dict(required=True, type='str', no_log=True),
domain=dict(required=True, type='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=True, type='str'),
# server
setup_ca=dict(required=True, type='bool'),
idstart=dict(required=True, type='int'),
idmax=dict(required=True, type='int'),
no_hbac_allow=dict(required=False, type='bool', default=False),
no_pkinit=dict(required=False, type='bool', default=False),
dirsrv_config_file=dict(required=False, type='str'),
_dirsrv_pkcs12_info=dict(required=False, type='list',
elements='str'),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', elements='str',
default=[]),
subject_base=dict(required=False, type='str'),
ca_subject=dict(required=False, type='str'),
# certificate system
external_cert_files=dict(required=False, type='list',
elements='str', default=[]),
# additional
domainlevel=dict(required=False, type='int',
default=MAX_DOMAIN_LEVEL),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# set values ####################################################
# basic
options.dm_password = ansible_module.params.get('dm_password')
options.admin_password = ansible_module.params.get('password')
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.idstart = ansible_module.params.get('idstart')
options.idmax = ansible_module.params.get('idmax')
options.no_hbac_allow = ansible_module.params.get('no_hbac_allow')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
options._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
options.ca_subject = ansible_module.params.get('ca_subject')
# certificate system
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
# additional
options.domainlevel = ansible_module.params.get('domainlevel')
options.domain_level = options.domainlevel
# init ##########################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
ds = ds_init_info(ansible_log, fstore,
options.domainlevel, options.dirsrv_config_file,
options.realm_name, options.host_name,
options.domain_name, options.dm_password,
options.idstart, options.idmax,
options.subject_base, options.ca_subject,
options.no_hbac_allow, options._dirsrv_pkcs12_info,
options.no_pkinit)
# set ds password ###############################################
with redirect_stdout(ansible_log):
ds.change_admin_password(options.admin_password)
# Force KDC to refresh the cached value of ipaKrbAuthzData by restarting.
# ipaKrbAuthzData has to be set with "MS-PAC" to trigger PAC generation,
# which is required to handle S4U2Proxy with the Bronze-Bit fix.
# Not doing so would cause API malfunction for around a minute, which is
# long enough to cause the hereafter client installation to fail.
krb = krbinstance.KrbInstance(fstore)
krb.set_output(ansible_log)
service.print_msg("Restarting the KDC")
krb.restart()
# done ##########################################################
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_setup_adtrust.py 0000664 0000000 0000000 00000010572 14600563364 0027541 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_setup_adtrust
short_description: Setup trust ad
description: Setup trust ad
options:
hostname:
description: Fully qualified name of this host
type: str
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
default: no
required: no
setup_adtrust:
description: Configure AD trust capability
type: bool
default: no
required: no
enable_compat:
description: Enable support for trusted domains for old clients
type: bool
default: no
required: no
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
type: int
required: no
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
type: int
required: no
adtrust_netbios_name:
description: The adtrust netbios_name setting
type: str
required: yes
adtrust_reset_netbios_name:
description: The adtrust reset_netbios_name setting
type: bool
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports, AnsibleModuleLog, setup_logging, options, sysrestore, paths,
api_Backend_ldap2, redirect_stdout, adtrust, api
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
hostname=dict(required=False, type='str'),
setup_ca=dict(required=False, type='bool', default=False),
setup_adtrust=dict(required=False, type='bool', default=False),
# ad trust
enable_compat=dict(required=False, type='bool', default=False),
rid_base=dict(required=False, type='int'),
secondary_rid_base=dict(required=False, type='int'),
# additional
adtrust_netbios_name=dict(required=True, type='str'),
adtrust_reset_netbios_name=dict(required=True, type='bool'),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# set values ####################################################
options.host_name = ansible_module.params.get('hostname')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
# ad trust
options.enable_compat = ansible_module.params.get('enable_compat')
options.rid_base = ansible_module.params.get('rid_base')
options.secondary_rid_base = ansible_module.params.get(
'secondary_rid_base')
# additional
adtrust.netbios_name = ansible_module.params.get('adtrust_netbios_name')
adtrust.reset_netbios_name = ansible_module.params.get(
'adtrust_reset_netbios_name')
# init ##########################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
# setup ds ######################################################
with redirect_stdout(ansible_log):
adtrust.install(False, options, fstore, api)
# done ##########################################################
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_setup_ca.py 0000664 0000000 0000000 00000035421 14600563364 0026436 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_setup_ca
short_description: Setup CA
description: Setup CA
options:
dm_password:
description: Directory Manager password
type: str
required: yes
password:
description: Admin user kerberos password
type: str
required: yes
master_password:
description: kerberos master password (normally autogenerated)
type: str
required: yes
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: no
no_host_dns:
description: Do not use DNS for hostname lookup during installation
type: bool
default: no
required: no
pki_config_override:
description: Path to ini file with config overrides
type: str
required: no
setup_adtrust:
description: Configure AD trust capability
type: bool
default: no
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
default: no
required: no
setup_dns:
description: Configure bind with our zone
type: bool
default: no
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
default: no
required: no
idstart:
description: The starting value for the IDs range (default random)
type: int
required: yes
idmax:
description: The max value for the IDs range (default idstart+199999)
type: int
required: yes
no_hbac_allow:
description: Don't install allow_all HBAC rule
type: bool
default: no
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
default: no
required: no
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
type: str
required: no
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
type: list
elements: str
required: no
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
type: list
elements: str
required: no
external_ca:
description: External ca setting
type: bool
default: no
required: no
external_ca_type:
description: Type of the external CA
type: str
required: no
external_ca_profile:
description:
Specify the certificate profile/template to use at the external CA
type: str
required: no
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
type: list
elements: str
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: no
_subject_base:
description: The installer _subject_base setting
type: str
required: no
ca_subject:
description: The installer ca_subject setting
type: str
required: no
_ca_subject:
description: The installer _ca_subject setting
type: str
required: no
ca_signing_algorithm:
description: Signing algorithm of the IPA CA certificate
type: str
required: no
_random_serial_numbers:
description: The installer _random_serial_numbers setting
type: bool
required: yes
reverse_zones:
description: The reverse DNS zones to use
type: list
elements: str
required: no
no_reverse:
description: Do not create new reverse DNS zone
type: bool
default: no
required: no
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
type: bool
default: no
required: no
domainlevel:
description: The domain level
type: int
required: no
_http_ca_cert:
description: The installer _http_ca_cert setting
type: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports, AnsibleModuleLog, setup_logging, options, sysrestore, paths,
ansible_module_get_parsed_ip_addresses,
api_Backend_ldap2, redirect_stdout, ca, installutils, ds_init_info,
custodiainstance, write_cache, x509, decode_certificate
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=True, type='str', no_log=True),
password=dict(required=True, type='str', no_log=True),
master_password=dict(required=True, type='str', no_log=True),
ip_addresses=dict(required=False, type='list', elements='str',
default=[]),
domain=dict(required=True, type='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=False, type='str'),
no_host_dns=dict(required=False, type='bool', default=False),
pki_config_override=dict(required=False, type='str'),
# server
setup_adtrust=dict(required=False, type='bool', default=False),
setup_kra=dict(required=False, type='bool', default=False),
setup_dns=dict(required=False, type='bool', default=False),
setup_ca=dict(required=False, type='bool', default=False),
idstart=dict(required=True, type='int'),
idmax=dict(required=True, type='int'),
no_hbac_allow=dict(required=False, type='bool', default=False),
no_pkinit=dict(required=False, type='bool', default=False),
dirsrv_config_file=dict(required=False, type='str'),
dirsrv_cert_files=dict(required=False, type='list',
elements='str'),
_dirsrv_pkcs12_info=dict(required=False, type='list',
elements='str'),
# certificate system
external_ca=dict(required=False, type='bool', default=False),
external_ca_type=dict(required=False, type='str'),
external_ca_profile=dict(required=False, type='str'),
external_cert_files=dict(required=False, type='list',
elements='str', default=None),
subject_base=dict(required=False, type='str'),
_subject_base=dict(required=False, type='str'),
ca_subject=dict(required=False, type='str'),
_ca_subject=dict(required=False, type='str'),
ca_signing_algorithm=dict(required=False, type='str'),
_random_serial_numbers=dict(required=True, type='bool'),
# dns
reverse_zones=dict(required=False, type='list', elements='str',
default=[]),
no_reverse=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
# additional
domainlevel=dict(required=False, type='int'),
_http_ca_cert=dict(required=False, type='str'),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# set values ############################################################
# basic
options.dm_password = ansible_module.params.get('dm_password')
options.admin_password = ansible_module.params.get('password')
options.master_password = ansible_module.params.get('master_password')
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
options.no_host_dns = ansible_module.params.get('no_host_dns')
options.pki_config_override = ansible_module.params.get(
'pki_config_override')
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
options.setup_ca = ansible_module.params.get('setup_ca')
options.idstart = ansible_module.params.get('idstart')
options.idmax = ansible_module.params.get('idmax')
options.no_hbac_allow = ansible_module.params.get('no_hbac_allow')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
options._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_ca_type = ansible_module.params.get('external_ca_type')
options.external_ca_profile = ansible_module.params.get(
'external_ca_profile')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
options._subject_base = ansible_module.params.get('_subject_base')
options.ca_subject = ansible_module.params.get('ca_subject')
options._ca_subject = ansible_module.params.get('_ca_subject')
options.ca_signing_algorithm = ansible_module.params.get(
'ca_signing_algorithm')
options._random_serial_numbers = ansible_module.params.get(
'_random_serial_numbers')
# dns
options.reverse_zones = ansible_module.params.get('reverse_zones')
options.no_reverse = ansible_module.params.get('no_reverse')
options.auto_forwarders = ansible_module.params.get('auto_forwarders')
# additional
options.domainlevel = ansible_module.params.get('domainlevel')
options._http_ca_cert = ansible_module.params.get('_http_ca_cert')
if options._http_ca_cert:
options._http_ca_cert = decode_certificate(options._http_ca_cert)
# init #################################################################
options.promote = False # first master, no promotion
# Repeat from ca.install_check
# ca.external_cert_file and ca.external_ca_file need to be set
if options.external_cert_files:
ca.external_cert_file, ca.external_ca_file = \
installutils.load_external_cert(
options.external_cert_files, options._ca_subject)
fstore = sysrestore.FileStore(paths.SYSRESTORE)
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
ds = ds_init_info(ansible_log, fstore,
options.domainlevel, options.dirsrv_config_file,
options.realm_name, options.host_name,
options.domain_name, options.dm_password,
options.idstart, options.idmax,
options.subject_base, options.ca_subject,
options.no_hbac_allow, options._dirsrv_pkcs12_info,
options.no_pkinit)
# setup custodia ########################################################
if hasattr(custodiainstance, "get_custodia_instance"):
if hasattr(custodiainstance.CustodiaModes, "FIRST_MASTER"):
mode = custodiainstance.CustodiaModes.FIRST_MASTER
else:
mode = custodiainstance.CustodiaModes.MASTER_PEER
custodia = custodiainstance.get_custodia_instance(options, mode)
else:
custodia = custodiainstance.CustodiaInstance(options.host_name,
options.realm_name)
custodia.set_output(ansible_log)
with redirect_stdout(ansible_log):
custodia.create_instance()
# setup CA ##############################################################
if options.setup_ca:
if not options.external_cert_files and options.external_ca:
# stage 1 of external CA installation
cache_vars = {n: options.__dict__[n] for o, n in options.knobs()
if n in options.__dict__}
write_cache(cache_vars)
try:
with redirect_stdout(ansible_log):
if hasattr(custodiainstance, "get_custodia_instance"):
ca.install_step_0(False, None, options, custodia=custodia)
else:
ca.install_step_0(False, None, options)
except SystemExit:
ansible_module.exit_json(changed=True,
csr_generated=True)
else:
# Put the CA cert where other instances expect it
x509.write_certificate(options._http_ca_cert, paths.IPA_CA_CRT)
os.chmod(paths.IPA_CA_CRT, 0o444)
if not options.no_pkinit:
x509.write_certificate(options._http_ca_cert,
paths.KDC_CA_BUNDLE_PEM)
else:
with open(paths.KDC_CA_BUNDLE_PEM, 'w'):
pass
os.chmod(paths.KDC_CA_BUNDLE_PEM, 0o444)
x509.write_certificate(options._http_ca_cert, paths.CA_BUNDLE_PEM)
os.chmod(paths.CA_BUNDLE_PEM, 0o444)
with redirect_stdout(ansible_log):
# we now need to enable ssl on the ds
ds.enable_ssl()
if options.setup_ca:
with redirect_stdout(ansible_log):
if hasattr(custodiainstance, "get_custodia_instance"):
ca.install_step_1(False, None, options, custodia=custodia)
else:
ca.install_step_1(False, None, options)
ansible_module.exit_json(changed=True,
csr_generated=False)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_setup_dns.py 0000664 0000000 0000000 00000014014 14600563364 0026632 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_setup_dns
short_description: Setup DNS
description: Setup DNS
options:
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: yes
setup_dns:
description: Configure bind with our zone
type: bool
required: yes
setup_ca:
description: Configure a dogtag CA
type: bool
required: yes
zonemgr:
description: DNS zone manager e-mail address. Defaults to hostmaster@DOMAIN
type: str
required: no
forwarders:
description: Add DNS forwarders
type: list
elements: str
required: yes
forward_policy:
description: DNS forwarding policy for global forwarders
type: str
choices: ['first', 'only']
default: 'first'
required: no
no_dnssec_validation:
description: Disable DNSSEC validation
type: bool
default: no
required: no
dns_ip_addresses:
description: The dns ip_addresses setting
type: list
elements: str
required: yes
dns_reverse_zones:
description: The dns reverse_zones setting
type: list
elements: str
required: yes
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports, AnsibleModuleLog, setup_logging, options, paths, dns,
ansible_module_get_parsed_ip_addresses, sysrestore, api_Backend_ldap2,
redirect_stdout, bindinstance
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
ip_addresses=dict(required=False, type='list', elements='str',
default=[]),
domain=dict(required=True, type='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=True, type='str'),
# server
setup_dns=dict(required=True, type='bool'),
setup_ca=dict(required=True, type='bool'),
# dns
zonemgr=dict(required=False, type='str'),
forwarders=dict(required=True, type='list', elements='str'),
forward_policy=dict(required=False, choices=['first', 'only'],
default='first'),
no_dnssec_validation=dict(required=False, type='bool',
default=False),
# additional
dns_ip_addresses=dict(required=True, type='list', elements='str'),
dns_reverse_zones=dict(required=True, type='list', elements='str'),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# set values ############################################################
# basic
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
# server
options.setup_dns = ansible_module.params.get('setup_dns')
options.setup_ca = ansible_module.params.get('setup_ca')
# dns
options.zonemgr = ansible_module.params.get('zonemgr')
options.forwarders = ansible_module.params.get('forwarders')
options.forward_policy = ansible_module.params.get('forward_policy')
options.no_dnssec_validation = ansible_module.params.get(
'no_dnssec_validation')
# additional
dns.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module, 'dns_ip_addresses')
dns.reverse_zones = ansible_module.params.get('dns_reverse_zones')
# init ##################################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
# setup dns #############################################################
with redirect_stdout(ansible_log):
if options.setup_dns:
dns.install(False, False, options)
else:
# Create a BIND instance
bind = bindinstance.BindInstance(fstore)
bind.set_output(ansible_log)
bind.setup(options.host_name, options.ip_addresses,
options.realm_name,
options.domain_name, (), 'first', (),
zonemgr=options.zonemgr,
no_dnssec_validation=options.no_dnssec_validation)
bind.create_file_with_system_records()
# done ##################################################################
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_setup_ds.py 0000664 0000000 0000000 00000021170 14600563364 0026455 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_setup_ds
short_description: Configure directory server
description: Configure directory server
options:
dm_password:
description: Directory Manager password
type: str
required: yes
password:
description: Admin user kerberos password
type: str
required: yes
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: no
idstart:
description: The starting value for the IDs range (default random)
type: int
required: yes
idmax:
description: The max value for the IDs range (default idstart+199999)
type: int
required: yes
no_hbac_allow:
description: Don't install allow_all HBAC rule
type: bool
default: no
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
default: no
required: no
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
type: str
required: no
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
type: list
elements: str
required: no
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
type: list
elements: str
required: no
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
type: list
elements: str
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: no
ca_subject:
description: The installer ca_subject setting
type: str
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
default: no
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports, AnsibleModuleLog, setup_logging, options, sysrestore, paths,
api_Backend_ldap2, redirect_stdout, api, NUM_VERSION, tasks,
dsinstance, ntpinstance, IPAAPI_USER
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=True, type='str', no_log=True),
password=dict(required=True, type='str', no_log=True),
domain=dict(required=True, type='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=False, type='str'),
# server
idstart=dict(required=True, type='int'),
idmax=dict(required=True, type='int'),
no_hbac_allow=dict(required=False, type='bool', default=False),
no_pkinit=dict(required=False, type='bool', default=False),
dirsrv_config_file=dict(required=False, type='str'),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', elements='str',
default=[]),
_dirsrv_pkcs12_info=dict(required=False, type='list',
elements='str'),
# certificate system
external_cert_files=dict(required=False, type='list',
elements='str', default=[]),
subject_base=dict(required=False, type='str'),
ca_subject=dict(required=False, type='str'),
# additional
setup_ca=dict(required=False, type='bool', default=False),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# set values ############################################################
# basic
options.dm_password = ansible_module.params.get('dm_password')
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
# server
options.idstart = ansible_module.params.get('idstart')
options.idmax = ansible_module.params.get('idmax')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.no_hbac_allow = ansible_module.params.get('no_hbac_allow')
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
options._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
# certificate system
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
options.ca_subject = ansible_module.params.get('ca_subject')
# additional
options.setup_ca = ansible_module.params.get('setup_ca')
# init ##################################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
# api Backend connect only if external_cert_files is not set
api_Backend_ldap2(options.host_name, options.setup_ca, connect=False)
# setup DS ##############################################################
# Make sure tmpfiles dir exist before installing components
if NUM_VERSION == 40504:
tasks.create_tmpfiles_dirs(IPAAPI_USER)
elif 40500 <= NUM_VERSION <= 40503:
tasks.create_tmpfiles_dirs()
# Create a directory server instance
if not options.external_cert_files:
ds = dsinstance.DsInstance(fstore=fstore,
domainlevel=options.domainlevel,
config_ldif=options.dirsrv_config_file)
ds.set_output(ansible_log)
if options.dirsrv_cert_files:
_dirsrv_pkcs12_info = options._dirsrv_pkcs12_info
else:
_dirsrv_pkcs12_info = None
with redirect_stdout(ansible_log):
ds.create_instance(options.realm_name, options.host_name,
options.domain_name,
options.dm_password, _dirsrv_pkcs12_info,
idstart=options.idstart, idmax=options.idmax,
subject_base=options.subject_base,
ca_subject=options.ca_subject,
hbac_allow=not options.no_hbac_allow,
setup_pkinit=not options.no_pkinit)
if not options.dirsrv_cert_files and NUM_VERSION < 40690:
ntpinstance.ntp_ldap_enable(options.host_name, ds.suffix,
options.realm_name)
else:
api.Backend.ldap2.connect()
ds = dsinstance.DsInstance(fstore=fstore,
domainlevel=options.domainlevel)
ds.set_output(ansible_log)
with redirect_stdout(ansible_log):
ds.init_info(
options.realm_name, options.host_name, options.domain_name,
options.dm_password,
options.subject_base, options.ca_subject, 1101, 1100, None,
setup_pkinit=not options.no_pkinit)
# done ##################################################################
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_setup_http.py 0000664 0000000 0000000 00000031616 14600563364 0027034 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_setup_http
short_description: Setup HTTP
description: Setup HTTP
options:
dm_password:
description: Directory Manager password
type: str
required: yes
password:
description: Admin user kerberos password
type: str
required: yes
master_password:
description: kerberos master password (normally autogenerated)
type: str
required: yes
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
reverse_zones:
description: The reverse DNS zones to use
type: list
elements: str
required: no
http_cert_files:
description:
File containing the Apache Server SSL certificate and private key
type: list
elements: str
required: no
setup_adtrust:
description: Configure AD trust capability
type: bool
default: no
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
default: no
required: no
setup_dns:
description: Configure bind with our zone
type: bool
default: no
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
default: no
required: no
no_host_dns:
description: Do not use DNS for hostname lookup during installation
type: bool
default: no
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
default: no
required: no
no_hbac_allow:
description: Don't install allow_all HBAC rule
type: bool
default: no
required: no
no_ui_redirect:
description: Do not automatically redirect to the Web UI
type: bool
default: no
required: no
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
type: list
elements: str
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: no
_subject_base:
description: The installer _subject_base setting
type: str
required: no
ca_subject:
description: The installer ca_subject setting
type: str
required: no
_ca_subject:
description: The installer _ca_subject setting
type: str
required: no
idstart:
description: The starting value for the IDs range (default random)
type: int
required: yes
idmax:
description: The max value for the IDs range (default idstart+199999)
type: int
required: yes
domainlevel:
description: The domain level
type: int
required: no
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
type: str
required: no
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
type: list
elements: str
required: no
no_reverse:
description: Do not create new reverse DNS zone
type: bool
default: no
required: no
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
type: bool
default: no
required: no
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
type: list
elements: str
required: no
_http_pkcs12_info:
description: The installer _http_pkcs12_info setting
type: list
elements: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports, AnsibleModuleLog, setup_logging, options, sysrestore, paths,
ansible_module_get_parsed_ip_addresses,
api_Backend_ldap2, redirect_stdout, ds_init_info,
krbinstance, httpinstance, ca, service, tasks
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=True, type='str', no_log=True),
password=dict(required=True, type='str', no_log=True),
master_password=dict(required=True, type='str', no_log=True),
domain=dict(required=True, type='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=False, type='str'),
ip_addresses=dict(required=False, type='list', elements='str',
default=[]),
reverse_zones=dict(required=False, type='list', elements='str',
default=[]),
http_cert_files=dict(required=False, type='list', elements='str',
default=[]),
setup_adtrust=dict(required=False, type='bool', default=False),
setup_kra=dict(required=False, type='bool', default=False),
setup_dns=dict(required=False, type='bool', default=False),
setup_ca=dict(required=False, type='bool', default=False),
no_host_dns=dict(required=False, type='bool', default=False),
no_pkinit=dict(required=False, type='bool', default=False),
no_hbac_allow=dict(required=False, type='bool', default=False),
no_ui_redirect=dict(required=False, type='bool', default=False),
external_cert_files=dict(required=False, type='list',
elements='str', default=[]),
subject_base=dict(required=False, type='str'),
_subject_base=dict(required=False, type='str'),
ca_subject=dict(required=False, type='str'),
_ca_subject=dict(required=False, type='str'),
idstart=dict(required=True, type='int'),
idmax=dict(required=True, type='int'),
domainlevel=dict(required=False, type='int'),
dirsrv_config_file=dict(required=False),
dirsrv_cert_files=dict(required=False, type='list', elements='str',
default=[]),
no_reverse=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
# _update_hosts_file=dict(required=False, type='bool',
# default=False),
_dirsrv_pkcs12_info=dict(required=False, type='list',
elements='str'),
_http_pkcs12_info=dict(required=False, type='list',
elements='str'),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# set values ############################################################
options.dm_password = ansible_module.params.get('dm_password')
options.admin_password = ansible_module.params.get('password')
options.master_password = ansible_module.params.get('master_password')
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.reverse_zones = ansible_module.params.get('reverse_zones')
options.http_cert_files = ansible_module.params.get('http_cert_files')
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
options.setup_ca = ansible_module.params.get('setup_ca')
options.no_host_dns = ansible_module.params.get('no_host_dns')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.no_hbac_allow = ansible_module.params.get('no_hbac_allow')
options.no_ui_redirect = ansible_module.params.get('no_ui_redirect')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
options._subject_base = ansible_module.params.get('_subject_base')
options.ca_subject = ansible_module.params.get('ca_subject')
options._ca_subject = ansible_module.params.get('_ca_subject')
options.no_reverse = ansible_module.params.get('no_reverse')
options.auto_forwarders = ansible_module.params.get('auto_forwarders')
options.idstart = ansible_module.params.get('idstart')
options.idmax = ansible_module.params.get('idmax')
options.domainlevel = ansible_module.params.get('domainlevel')
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
# options._update_hosts_file = ansible_module.params.get(
# '_update_hosts_file')
options._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
options._http_pkcs12_info = ansible_module.params.get(
'_http_pkcs12_info')
# init ##################################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
ds = ds_init_info(ansible_log, fstore,
options.domainlevel, options.dirsrv_config_file,
options.realm_name, options.host_name,
options.domain_name, options.dm_password,
options.idstart, options.idmax,
options.subject_base, options.ca_subject,
options.no_hbac_allow, options._dirsrv_pkcs12_info,
options.no_pkinit)
# krb
krb = krbinstance.KrbInstance(fstore)
krb.set_output(ansible_log)
with redirect_stdout(ansible_log):
krb.init_info(options.realm_name, options.host_name,
setup_pkinit=not options.no_pkinit,
subject_base=options.subject_base)
# setup HTTP ############################################################
# Create a HTTP instance
http = httpinstance.HTTPInstance(fstore)
http.set_output(ansible_log)
with redirect_stdout(ansible_log):
if options.http_cert_files:
http.create_instance(
options.realm_name, options.host_name, options.domain_name,
options.dm_password,
pkcs12_info=options._http_pkcs12_info,
subject_base=options.subject_base,
auto_redirect=not options.no_ui_redirect,
ca_is_configured=options.setup_ca)
else:
http.create_instance(
options.realm_name, options.host_name, options.domain_name,
options.dm_password,
subject_base=options.subject_base,
auto_redirect=not options.no_ui_redirect,
ca_is_configured=options.setup_ca)
if hasattr(paths, "CACHE_IPA_SESSIONS"):
tasks.restore_context(paths.CACHE_IPA_SESSIONS)
ca.set_subject_base_in_config(options.subject_base)
# configure PKINIT now that all required services are in place
krb.enable_ssl()
# Apply any LDAP updates. Needs to be done after the configuration file
# is created. DS is restarted in the process.
service.print_msg("Applying LDAP updates")
ds.apply_updates()
# Restart krb after configurations have been changed
service.print_msg("Restarting the KDC")
krb.restart()
# done ##################################################################
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_setup_kra.py 0000664 0000000 0000000 00000007775 14600563364 0026643 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_setup_kra
short_description: Setup KRA
description: Setup KRA
options:
dm_password:
description: Directory Manager password
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: yes
setup_ca:
description: Configure a dogtag CA
type: bool
required: yes
setup_kra:
description: Configure a dogtag KRA
type: bool
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
pki_config_override:
description: Path to ini file with config overrides
type: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports, AnsibleModuleLog, setup_logging, options,
api_Backend_ldap2, redirect_stdout, api, custodiainstance, kra
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=True, type='str', no_log=True),
hostname=dict(required=True, type='str'),
setup_ca=dict(required=True, type='bool'),
setup_kra=dict(required=True, type='bool'),
realm=dict(required=True, type='str'),
pki_config_override=dict(required=False, type='str'),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# set values ####################################################
options.dm_password = ansible_module.params.get('dm_password')
options.host_name = ansible_module.params.get('hostname')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.realm_name = ansible_module.params.get('realm')
options.pki_config_override = ansible_module.params.get(
'pki_config_override')
options.promote = False # first master, no promotion
# init ##########################################################
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
# setup kra #####################################################
with redirect_stdout(ansible_log):
if hasattr(custodiainstance, "get_custodia_instance"):
if hasattr(custodiainstance.CustodiaModes, "FIRST_MASTER"):
mode = custodiainstance.CustodiaModes.FIRST_MASTER
else:
mode = custodiainstance.CustodiaModes.MASTER_PEER
custodia = custodiainstance.get_custodia_instance(options, mode)
kra.install(api, None, options, custodia=custodia)
else:
kra.install(api, None, options)
# done ##########################################################
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_setup_krb.py 0000664 0000000 0000000 00000021627 14600563364 0026634 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_setup_krb
short_description: Setup KRB
description: Setup KRB
options:
dm_password:
description: Directory Manager password
type: str
required: yes
password:
description: Admin user kerberos password
type: str
required: yes
master_password:
description: kerberos master password (normally autogenerated)
type: str
required: yes
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: yes
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: no
ip_addresses:
description: List of Master Server IP Addresses
type: list
elements: str
required: no
reverse_zones:
description: The reverse DNS zones to use
type: list
elements: str
required: no
setup_adtrust:
description: Configure AD trust capability
type: bool
default: no
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
default: no
required: no
setup_dns:
description: Configure bind with our zone
type: bool
default: no
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
default: no
required: no
no_host_dns:
description: Do not use DNS for hostname lookup during installation
type: bool
default: no
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
default: no
required: no
no_hbac_allow:
description: Don't install allow_all HBAC rule
type: bool
default: no
required: no
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
type: list
elements: str
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: no
ca_subject:
description: The installer ca_subject setting
type: str
required: no
idstart:
description: The starting value for the IDs range (default random)
type: int
required: yes
idmax:
description: The max value for the IDs range (default idstart+199999)
type: int
required: yes
no_reverse:
description: Do not create new reverse DNS zone
type: bool
default: no
required: no
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
type: bool
default: no
required: no
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
type: list
elements: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports, AnsibleModuleLog, setup_logging, options, sysrestore, paths,
ansible_module_get_parsed_ip_addresses,
api_Backend_ldap2, redirect_stdout, krbinstance
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=True, type='str', no_log=True),
password=dict(required=True, type='str', no_log=True),
master_password=dict(required=True, type='str', no_log=True),
domain=dict(required=True, type='str'),
realm=dict(required=True, type='str'),
hostname=dict(required=False, type='str'),
ip_addresses=dict(required=False, type='list', elements='str',
default=[]),
reverse_zones=dict(required=False, type='list', elements='str',
default=[]),
setup_adtrust=dict(required=False, type='bool', default=False),
setup_kra=dict(required=False, type='bool', default=False),
setup_dns=dict(required=False, type='bool', default=False),
setup_ca=dict(required=False, type='bool', default=False),
no_host_dns=dict(required=False, type='bool', default=False),
no_pkinit=dict(required=False, type='bool', default=False),
no_hbac_allow=dict(required=False, type='bool', default=False),
external_cert_files=dict(required=False, type='list',
elements='str', default=[]),
subject_base=dict(required=False, type='str'),
ca_subject=dict(required=False, type='str'),
idstart=dict(required=True, type='int'),
idmax=dict(required=True, type='int'),
no_reverse=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
_pkinit_pkcs12_info=dict(required=False, type='list',
elements='str'),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# set values ############################################################
options.dm_password = ansible_module.params.get('dm_password')
options.admin_password = ansible_module.params.get('password')
options.master_password = ansible_module.params.get('master_password')
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.reverse_zones = ansible_module.params.get('reverse_zones')
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
options.setup_ca = ansible_module.params.get('setup_ca')
options.no_host_dns = ansible_module.params.get('no_host_dns')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.no_hbac_allow = ansible_module.params.get('no_hbac_allow')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
options.ca_subject = ansible_module.params.get('ca_subject')
options.no_reverse = ansible_module.params.get('no_reverse')
options.auto_forwarders = ansible_module.params.get('auto_forwarders')
options.idstart = ansible_module.params.get('idstart')
options.idmax = ansible_module.params.get('idmax')
options._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
# options._update_hosts_file = ansible_module.params.get(
# 'update_hosts_file')
# init ##################################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
# setup KRB #############################################################
krb = krbinstance.KrbInstance(fstore)
krb.set_output(ansible_log)
with redirect_stdout(ansible_log):
if not options.external_cert_files:
krb.create_instance(options.realm_name, options.host_name,
options.domain_name,
options.dm_password, options.master_password,
setup_pkinit=not options.no_pkinit,
pkcs12_info=options._pkinit_pkcs12_info,
subject_base=options.subject_base)
else:
krb.init_info(options.realm_name, options.host_name,
setup_pkinit=not options.no_pkinit,
subject_base=options.subject_base)
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_setup_ntp.py 0000664 0000000 0000000 00000007651 14600563364 0026660 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_setup_ntp
short_description: Setup NTP
description: Setup NTP
options:
ntp_servers:
description: ntp servers to use
type: list
elements: str
required: no
ntp_pool:
description: ntp server pool to use
type: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports, AnsibleModuleLog, setup_logging, options, sysrestore, paths,
redirect_stdout, time_service, sync_time, ntpinstance, timeconf,
getargspec
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
ntp_servers=dict(required=False, type='list', elements='str',
default=None),
ntp_pool=dict(required=False, type='str', default=None),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# set values ############################################################
options.ntp_servers = ansible_module.params.get('ntp_servers')
options.ntp_pool = ansible_module.params.get('ntp_pool')
# init ##########################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
# setup NTP #####################################################
if time_service == "chronyd":
# We have to sync time before certificate handling on master.
# As chrony configuration is moved from client here, unconfiguration of
# chrony will be handled here in uninstall() method as well by invoking
# the ipa-server-install --uninstall
ansible_module.log("Synchronizing time")
# pylint: disable=deprecated-method
argspec = getargspec(sync_time)
# pylint: enable=deprecated-method
if "options" not in argspec.args:
synced_ntp = sync_time(options.ntp_servers, options.ntp_pool,
fstore, sstore)
else:
synced_ntp = sync_time(options, fstore, sstore)
if not synced_ntp:
ansible_module.log(
"Warning: IPA was unable to sync time with chrony!")
ansible_module.log(
" Time synchronization is required for IPA "
"to work correctly")
else:
# Configure ntpd
timeconf.force_ntpd(sstore)
ntp = ntpinstance.NTPInstance(fstore)
ntp.set_output(ansible_log)
with redirect_stdout(ansible_log):
if not ntp.is_configured():
ntp.create_instance()
# done ##########################################################
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_setup_otpd.py 0000664 0000000 0000000 00000006010 14600563364 0027011 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_setup_otpd
short_description: Setup OTPD
description: Setup OTPD
options:
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: yes
hostname:
description: Fully qualified name of this host
type: str
required: no
setup_ca:
description: Configure a dogtag CA
type: bool
default: no
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
check_imports, AnsibleModuleLog, setup_logging, options,
api_Backend_ldap2, redirect_stdout, otpdinstance, ipautil
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
realm=dict(required=True, type='str'),
hostname=dict(required=False, type='str'),
setup_ca=dict(required=False, type='bool', default=False),
),
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# set values ####################################################
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
options.setup_ca = ansible_module.params.get('setup_ca')
# init ##########################################################
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
# setup ds ######################################################
otpd = otpdinstance.OtpdInstance()
otpd.set_output(ansible_log)
with redirect_stdout(ansible_log):
otpd.create_instance('OTPD', options.host_name,
ipautil.realm_to_suffix(options.realm_name))
# done ##########################################################
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/library/ipaserver_test.py 0000664 0000000 0000000 00000135164 14600563364 0025617 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipaserver_test
short_description: IPA server test
description: IPA server test
options:
force:
description: Installer force parameter
type: bool
default: no
required: no
dm_password:
description: Directory Manager password
type: str
required: yes
password:
description: Admin user kerberos password
type: str
required: yes
master_password:
description: kerberos master password (normally autogenerated)
type: str
required: no
domain:
description: Primary DNS domain of the IPA deployment
type: str
required: no
realm:
description: Kerberos realm name of the IPA deployment
type: str
required: no
hostname:
description: Fully qualified name of this host
type: str
required: no
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
type: list
elements: str
required: no
no_host_dns:
description: Do not use DNS for hostname lookup during installation
type: bool
default: no
required: no
pki_config_override:
description: Path to ini file with config overrides
type: str
required: no
skip_mem_check:
description: Skip checking for minimum required memory
type: bool
default: no
required: no
setup_adtrust:
description: Configure AD trust capability
type: bool
default: no
required: no
setup_kra:
description: Configure a dogtag KRA
type: bool
default: no
required: no
setup_dns:
description: Configure bind with our zone
type: bool
default: no
required: no
idstart:
description: The starting value for the IDs range (default random)
type: int
required: no
idmax:
description: The max value for the IDs range (default idstart+199999)
type: int
required: no
no_pkinit:
description: Disable pkinit setup steps
type: bool
default: no
required: no
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
type: str
required: no
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
type: list
elements: str
required: no
http_cert_files:
description:
File containing the Apache Server SSL certificate and private key
type: list
elements: str
required: no
pkinit_cert_files:
description:
File containing the Kerberos KDC SSL certificate and private key
type: list
elements: str
required: no
dirsrv_pin:
description: The password to unlock the Directory Server private key
type: str
required: no
http_pin:
description: The password to unlock the Apache Server private key
type: str
required: no
pkinit_pin:
description: The password to unlock the Kerberos KDC private key
type: str
required: no
dirsrv_cert_name:
description: Name of the Directory Server SSL certificate to install
type: str
required: no
http_cert_name:
description: Name of the Apache Server SSL certificate to install
type: str
required: no
pkinit_cert_name:
description: Name of the Kerberos KDC SSL certificate to install
type: str
required: no
ntp_servers:
description: ntp servers to use
type: list
elements: str
required: no
ntp_pool:
description: ntp server pool to use
type: str
required: no
no_ntp:
description: Do not configure ntp
type: bool
default: no
required: no
external_ca:
description: External ca setting
type: bool
default: no
required: no
external_ca_type:
description: Type of the external CA
type: str
required: no
external_ca_profile:
description:
Specify the certificate profile/template to use at the external CA
type: str
required: no
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
type: list
elements: str
required: no
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
type: str
required: no
ca_subject:
description: The installer ca_subject setting
type: str
required: no
random_serial_numbers:
description: The installer random_serial_numbers setting
type: bool
default: no
required: no
allow_zone_overlap:
description: Create DNS zone even if it already exists
type: bool
default: no
required: no
reverse_zones:
description: The reverse DNS zones to use
type: list
elements: str
required: no
no_reverse:
description: Do not create new reverse DNS zone
type: bool
default: no
required: no
auto_reverse:
description: Create necessary reverse zones
type: bool
default: no
required: no
zonemgr:
description: DNS zone manager e-mail address. Defaults to hostmaster@DOMAIN
type: str
required: no
forwarders:
description: Add DNS forwarders
type: list
elements: str
required: no
no_forwarders:
description: Do not add any DNS forwarders, use root servers instead
type: bool
default: no
required: no
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
type: bool
default: no
required: no
forward_policy:
description: DNS forwarding policy for global forwarders
type: str
choices: ['first', 'only']
required: no
no_dnssec_validation:
description: Disable DNSSEC validation
type: bool
default: no
required: no
enable_compat:
description: Enable support for trusted domains for old clients
type: bool
default: no
required: no
netbios_name:
description: NetBIOS name of the IPA domain
type: str
required: no
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
type: int
default: 1000
required: no
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
type: int
default: 100000000
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
import sys
import random
from shutil import copyfile
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_native
from ansible.module_utils.ansible_ipa_server import (
check_imports,
AnsibleModuleLog, setup_logging, options, adtrust_imported, kra_imported,
PKIIniLoader, MIN_DOMAIN_LEVEL, MAX_DOMAIN_LEVEL, check_zone_overlap,
redirect_stdout, validate_dm_password, validate_admin_password,
NUM_VERSION, is_ipa_configured, sysrestore, paths, bindinstance,
read_cache, ca, tasks, check_ldap_conf, timeconf, httpinstance,
check_dirsrv, ScriptError, get_fqdn, verify_fqdn, BadHostError,
validate_domain_name, load_pkcs12, IPA_PYTHON_VERSION,
encode_certificate, check_available_memory, getargspec, adtrustinstance,
get_min_idstart, SerialNumber
)
from ansible.module_utils import six
if six.PY3:
unicode = str
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
force=dict(required=False, type='bool', default=False),
dm_password=dict(required=True, type='str', no_log=True),
password=dict(required=True, type='str', no_log=True),
master_password=dict(required=False, type='str', no_log=True),
domain=dict(required=False, type='str'),
realm=dict(required=False, type='str'),
hostname=dict(required=False, type='str'),
ca_cert_files=dict(required=False, type='list', elements='str',
default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
pki_config_override=dict(required=False, type='str'),
skip_mem_check=dict(required=False, type='bool', default=False),
# server
setup_adtrust=dict(required=False, type='bool', default=False),
setup_kra=dict(required=False, type='bool', default=False),
setup_dns=dict(required=False, type='bool', default=False),
idstart=dict(required=False, type='int'),
idmax=dict(required=False, type='int'),
# no_hbac_allow
no_pkinit=dict(required=False, type='bool', default=False),
# no_ui_redirect
dirsrv_config_file=dict(required=False, type='str'),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', elements='str',
default=None),
http_cert_files=dict(required=False, type='list', elements='str',
default=None),
pkinit_cert_files=dict(required=False, type='list', elements='str',
default=None),
dirsrv_pin=dict(required=False, type='str'),
http_pin=dict(required=False, type='str'),
pkinit_pin=dict(required=False, type='str'),
dirsrv_cert_name=dict(required=False, type='str'),
http_cert_name=dict(required=False, type='str'),
pkinit_cert_name=dict(required=False, type='str'),
# client
# mkhomedir
ntp_servers=dict(required=False, type='list', elements='str',
default=None),
ntp_pool=dict(required=False, type='str', default=None),
no_ntp=dict(required=False, type='bool', default=False),
# ssh_trust_dns
# no_ssh
# no_sshd
# no_dns_sshfp
# certificate system
external_ca=dict(required=False, type='bool', default=False),
external_ca_type=dict(required=False, type='str'),
external_ca_profile=dict(required=False, type='str'),
external_cert_files=dict(required=False, type='list',
elements='str', default=None),
subject_base=dict(required=False, type='str'),
ca_subject=dict(required=False, type='str'),
random_serial_numbers=dict(required=False, type='bool',
default=False),
# ca_signing_algorithm
# dns
allow_zone_overlap=dict(required=False, type='bool',
default=False),
reverse_zones=dict(required=False, type='list', elements='str',
default=[]),
no_reverse=dict(required=False, type='bool', default=False),
auto_reverse=dict(required=False, type='bool', default=False),
zonemgr=dict(required=False, type='str'),
forwarders=dict(required=False, type='list', elements='str',
default=[]),
no_forwarders=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
forward_policy=dict(required=False, type='str',
choices=['first', 'only'], default=None),
no_dnssec_validation=dict(required=False, type='bool',
default=False),
# ad trust
enable_compat=dict(required=False, type='bool', default=False),
netbios_name=dict(required=False, type='str'),
rid_base=dict(required=False, type='int', default=1000),
secondary_rid_base=dict(required=False, type='int',
default=100000000),
# additional
),
supports_check_mode=False,
)
ansible_module._ansible_debug = True
check_imports(ansible_module)
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# set values ############################################################
# basic
options.force = ansible_module.params.get('force')
options.dm_password = ansible_module.params.get('dm_password')
options.admin_password = ansible_module.params.get('password')
options.master_password = ansible_module.params.get('master_password')
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.no_host_dns = ansible_module.params.get('no_host_dns')
options.pki_config_override = ansible_module.params.get(
'pki_config_override')
options.skip_mem_check = ansible_module.params.get('skip_mem_check')
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_dns = ansible_module.params.get('setup_dns')
options.setup_kra = ansible_module.params.get('setup_kra')
options.idstart = ansible_module.params.get('idstart')
options.idmax = ansible_module.params.get('idmax')
# no_hbac_allow
options.no_pkinit = ansible_module.params.get('no_pkinit')
# no_ui_redirect
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
options.http_cert_files = ansible_module.params.get('http_cert_files')
options.pkinit_cert_files = ansible_module.params.get('pkinit_cert_files')
options.dirsrv_pin = ansible_module.params.get('dirsrv_pin')
options.http_pin = ansible_module.params.get('http_pin')
options.pkinit_pin = ansible_module.params.get('pkinit_pin')
options.dirsrv_cert_name = ansible_module.params.get('dirsrv_cert_name')
options.http_cert_name = ansible_module.params.get('http_cert_name')
options.pkinit_cert_name = ansible_module.params.get('pkinit_cert_name')
# client
# mkhomedir
options.ntp_servers = ansible_module.params.get('ntp_servers')
options.ntp_pool = ansible_module.params.get('ntp_pool')
options.no_ntp = ansible_module.params.get('no_ntp')
# ssh_trust_dns
# no_ssh
# no_sshd
# no_dns_sshfp
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_ca_type = ansible_module.params.get('external_ca_type')
options.external_ca_profile = ansible_module.params.get(
'external_ca_profile')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
options.ca_subject = ansible_module.params.get('ca_subject')
options._random_serial_numbers = ansible_module.params.get(
'random_serial_numbers')
# ca_signing_algorithm
# dns
options.allow_zone_overlap = ansible_module.params.get(
'allow_zone_overlap')
options.reverse_zones = ansible_module.params.get('reverse_zones')
options.no_reverse = ansible_module.params.get('no_reverse')
options.auto_reverse = ansible_module.params.get('auto_reverse')
options.zonemgr = ansible_module.params.get('zonemgr')
options.forwarders = ansible_module.params.get('forwarders')
options.no_forwarders = ansible_module.params.get('no_forwarders')
options.auto_forwarders = ansible_module.params.get('auto_forwarders')
options.forward_policy = ansible_module.params.get('forward_policy')
options.no_dnssec_validation = ansible_module.params.get(
'no_dnssec_validation')
# ad trust
options.enable_compat = ansible_module.params.get('enable_compat')
options.netbios_name = ansible_module.params.get('netbios_name')
options.rid_base = ansible_module.params.get('rid_base')
options.secondary_rid_base = ansible_module.params.get(
'secondary_rid_base')
# additional
options.kasp_db_file = None
# version specific ######################################################
sid_generation_always = False
if not options.setup_adtrust:
# pylint: disable=deprecated-method
argspec = getargspec(adtrustinstance.ADTRUSTInstance.__init__)
# pylint: enable=deprecated-method
if "fulltrust" in argspec.args:
sid_generation_always = True
else:
if not adtrust_imported:
ansible_module.fail_json(msg="adtrust can not be imported")
if options.setup_kra and not kra_imported:
# if "kra" not in options._allow_missing:
ansible_module.fail_json(msg="kra can not be imported")
# else:
# options.setup_kra = False
# ansible_module.warn(msg="kra is not supported, disabling")
if options.pki_config_override is not None:
if PKIIniLoader is None:
ansible_module.warn("The use of pki_config_override is not "
"supported for this IPA version")
else:
# From DogtagInstallInterface @pki_config_override.validator
try:
PKIIniLoader.verify_pki_config_override(
options.pki_config_override)
except ValueError as e:
ansible_module.fail_json(
msg="pki_config_override: %s" % str(e))
# Check if Random Serial Numbers v3 is available
if options._random_serial_numbers and SerialNumber is None:
ansible_module.fail_json(
msg="Random Serial Numbers is not supported for this IPA version"
)
# default values ########################################################
# idstart and idmax
if options.idstart is None:
options.idstart = random.randint(1, 10000) * 200000
if options.idmax is None or options.idmax == 0:
options.idmax = options.idstart + 199999
# ServerInstallInterface.__init__ #######################################
try:
self = options
# If any of the key file options are selected, all are required.
cert_file_req = (self.dirsrv_cert_files, self.http_cert_files)
cert_file_opt = (self.pkinit_cert_files,)
if not self.no_pkinit:
cert_file_req += cert_file_opt
if self.no_pkinit and self.pkinit_cert_files:
raise RuntimeError(
"--no-pkinit and --pkinit-cert-file cannot be specified "
"together"
)
if any(cert_file_req + cert_file_opt) and not all(cert_file_req):
raise RuntimeError(
"--dirsrv-cert-file, --http-cert-file, and --pkinit-cert-file "
"or --no-pkinit are required if any key file options are used."
)
if not self.interactive:
if self.dirsrv_cert_files and self.dirsrv_pin is None:
raise RuntimeError(
"You must specify --dirsrv-pin with --dirsrv-cert-file")
if self.http_cert_files and self.http_pin is None:
raise RuntimeError(
"You must specify --http-pin with --http-cert-file")
if self.pkinit_cert_files and self.pkinit_pin is None:
raise RuntimeError(
"You must specify --pkinit-pin with --pkinit-cert-file")
if not self.setup_dns:
if self.forwarders:
raise RuntimeError(
"You cannot specify a --forwarder option without the "
"--setup-dns option")
if self.auto_forwarders:
raise RuntimeError(
"You cannot specify a --auto-forwarders option without "
"the --setup-dns option")
if self.no_forwarders:
raise RuntimeError(
"You cannot specify a --no-forwarders option without the "
"--setup-dns option")
if self.forward_policy:
raise RuntimeError(
"You cannot specify a --forward-policy option without the "
"--setup-dns option")
if self.reverse_zones:
raise RuntimeError(
"You cannot specify a --reverse-zone option without the "
"--setup-dns option")
if self.auto_reverse:
raise RuntimeError(
"You cannot specify a --auto-reverse option without the "
"--setup-dns option")
if self.no_reverse:
raise RuntimeError(
"You cannot specify a --no-reverse option without the "
"--setup-dns option")
if self.no_dnssec_validation:
raise RuntimeError(
"You cannot specify a --no-dnssec-validation option "
"without the --setup-dns option")
elif self.forwarders and self.no_forwarders:
raise RuntimeError(
"You cannot specify a --forwarder option together with "
"--no-forwarders")
elif self.auto_forwarders and self.no_forwarders:
raise RuntimeError(
"You cannot specify a --auto-forwarders option together with "
"--no-forwarders")
elif self.reverse_zones and self.no_reverse:
raise RuntimeError(
"You cannot specify a --reverse-zone option together with "
"--no-reverse")
elif self.auto_reverse and self.no_reverse:
raise RuntimeError(
"You cannot specify a --auto-reverse option together with "
"--no-reverse")
if not self.setup_adtrust:
if self.add_agents:
raise RuntimeError(
"You cannot specify an --add-agents option without the "
"--setup-adtrust option")
if self.enable_compat:
raise RuntimeError(
"You cannot specify an --enable-compat option without the "
"--setup-adtrust option")
# Deactivate test for new IPA SID generation
if self.netbios_name and not sid_generation_always:
raise RuntimeError(
"You cannot specify a --netbios-name option without the "
"--setup-adtrust option")
if self.no_msdcs:
raise RuntimeError(
"You cannot specify a --no-msdcs option without the "
"--setup-adtrust option")
if not hasattr(self, 'replica_install'):
if self.external_cert_files and self.dirsrv_cert_files:
raise RuntimeError(
"Service certificate file options cannot be used with the "
"external CA options.")
if self.external_ca_type and not self.external_ca:
raise RuntimeError(
"You cannot specify --external-ca-type without "
"--external-ca")
if self.external_ca_profile and not self.external_ca:
raise RuntimeError(
"You cannot specify --external-ca-profile without "
"--external-ca")
if self.uninstalling:
if (self.realm_name or self.admin_password or
self.master_password):
raise RuntimeError(
"In uninstall mode, -a, -r and -P options are not "
"allowed")
elif not self.interactive:
if (not self.realm_name or not self.dm_password or
not self.admin_password):
raise RuntimeError(
"In unattended mode you need to provide at least -r, "
"-p and -a options")
if self.setup_dns:
if (not self.forwarders and
not self.no_forwarders and
not self.auto_forwarders):
raise RuntimeError(
"You must specify at least one of --forwarder, "
"--auto-forwarders, or --no-forwarders options")
any_ignore_option_true = any(
[self.ignore_topology_disconnect, self.ignore_last_of_role])
if any_ignore_option_true and not self.uninstalling:
raise RuntimeError(
"'--ignore-topology-disconnect/--ignore-last-of-role' "
"options can be used only during uninstallation")
if get_min_idstart is not None:
min_idstart = get_min_idstart()
if self.idstart < min_idstart:
raise RuntimeError(
"idstart (%i) must be larger than UID_MAX/GID_MAX "
"(%i) setting in /etc/login.defs." % (
self.idstart, min_idstart
)
)
if self.idmax < self.idstart:
raise RuntimeError(
"idmax (%s) cannot be smaller than idstart (%s)" %
(self.idmax, self.idstart))
else:
# replica installers
if self.servers and not self.domain_name:
raise RuntimeError(
"The --server option cannot be used without providing "
"domain via the --domain option")
if self.setup_dns:
if (not self.forwarders and
not self.no_forwarders and
not self.auto_forwarders):
raise RuntimeError(
"You must specify at least one of --forwarder, "
"--auto-forwarders, or --no-forwarders options")
except RuntimeError as e:
ansible_module.fail_json(msg=to_native(e))
# #######################################################################
# If any of the key file options are selected, all are required.
cert_file_req = (options.dirsrv_cert_files, options.http_cert_files)
cert_file_opt = (options.pkinit_cert_files,)
if not options.no_pkinit:
cert_file_req += cert_file_opt
if options.no_pkinit and options.pkinit_cert_files:
ansible_module.fail_json(
msg="no-pkinit and pkinit-cert-file cannot be specified together"
)
if any(cert_file_req + cert_file_opt) and not all(cert_file_req):
ansible_module.fail_json(
msg="dirsrv-cert-file, http-cert-file, and pkinit-cert-file "
"or no-pkinit are required if any key file options are used."
)
if not options.interactive:
if options.dirsrv_cert_files and options.dirsrv_pin is None:
ansible_module.fail_json(
msg="You must specify dirsrv-pin with dirsrv-cert-file")
if options.http_cert_files and options.http_pin is None:
ansible_module.fail_json(
msg="You must specify http-pin with http-cert-file")
if options.pkinit_cert_files and options.pkinit_pin is None:
ansible_module.fail_json(
msg="You must specify pkinit-pin with pkinit-cert-file")
if not options.setup_dns:
# lists
for x in ["forwarders", "reverse_zones"]:
if len(getattr(options, x)) > 1:
ansible_module.fail_json(
msg="You cannot specify %s without setting setup-dns" % x)
# bool and str values
for x in ["auto_forwarders", "no_forwarders",
"auto_reverse", "no_reverse", "no_dnssec_validation",
"forward_policy"]:
if getattr(options, x):
ansible_module.fail_json(
msg="You cannot specify %s without setting setup-dns" % x)
elif len(options.forwarders) > 0 and options.no_forwarders:
ansible_module.fail_json(
msg="You cannot specify forwarders together with no-forwarders")
elif options.auto_forwarders and options.no_forwarders:
ansible_module.fail_json(
msg="You cannot specify auto-forwarders together with "
"no-forwarders")
elif len(options.reverse_zones) > 0 and options.no_reverse:
ansible_module.fail_json(
msg="You cannot specify reverse-zones together with no-reverse")
elif options.auto_reverse and options.no_reverse:
ansible_module.fail_json(
msg="You cannot specify auto-reverse together with no-reverse")
if not hasattr(self, 'replica_install'):
if options.external_cert_files and options.dirsrv_cert_files:
ansible_module.fail_json(
msg="Service certificate file options cannot be used with the "
"external CA options.")
if options.external_ca_type and not options.external_ca:
ansible_module.fail_json(
msg="You cannot specify external-ca-type without external-ca")
# if options.uninstalling:
# if (options.realm_name or options.admin_password or
# options.master_password):
# ansible_module.fail_json(
# msg="In uninstall mode, -a, -r and -P options are not "
# "allowed")
# elif not options.interactive:
# if (not options.realm_name or not options.dm_password or
# not options.admin_password):
# ansible_module.fail_json(msg=
# "In unattended mode you need to provide at least -r, "
# "-p and -a options")
# if options.setup_dns:
# if (not options.forwarders and
# not options.no_forwarders and
# not options.auto_forwarders):
# ansible_module.fail_json(msg=
# "You must specify at least one of --forwarder, "
# "--auto-forwarders, or --no-forwarders options")
if (not options.realm_name or not options.dm_password or
not options.admin_password):
ansible_module.fail_json(
msg="You need to provide at least realm_name, dm_password "
"and admin_password")
if options.setup_dns:
if len(options.forwarders) < 1 and not options.no_forwarders and \
not options.auto_forwarders:
ansible_module.fail_json(
msg="You must specify at least one of forwarders, "
"auto-forwarders or no-forwarders")
# any_ignore_option_true = any(
# [options.ignore_topology_disconnect, options.ignore_last_of_role])
# if any_ignore_option_true and not options.uninstalling:
# ansible_module.fail_json(
# msg="ignore-topology-disconnect and ignore-last-of-role "
# "can be used only during uninstallation")
if options.idmax < options.idstart:
ansible_module.fail_json(
msg="idmax (%s) cannot be smaller than idstart (%s)" %
(options.idmax, options.idstart))
# validation #############################################################
if options.dm_password is None:
ansible_module.fail_json(msg="Directory Manager password required")
if options.admin_password is None:
ansible_module.fail_json(msg="IPA admin password required")
# validation ############################################################
# domain_level
if options.domain_level < MIN_DOMAIN_LEVEL:
ansible_module.fail_json(
msg="Domain Level cannot be lower than %d" % MIN_DOMAIN_LEVEL)
elif options.domain_level > MAX_DOMAIN_LEVEL:
ansible_module.fail_json(
msg="Domain Level cannot be higher than %d" % MAX_DOMAIN_LEVEL)
# dirsrv_config_file
if options.dirsrv_config_file is not None:
if not os.path.exists(options.dirsrv_config_file):
ansible_module.fail_json(
msg="File %s does not exist." % options.dirsrv_config_file)
# domain_name
# Validation is done later on in ipaserver_prepare dns.install_check
# dm_password
with redirect_stdout(ansible_log):
validate_dm_password(options.dm_password)
# admin_password
with redirect_stdout(ansible_log):
validate_admin_password(options.admin_password)
# pkinit is not supported on DL0, don't allow related options
# pylint: disable=pointless-string-statement
"""
# replica install: if not options.replica_file is None:
if (not options._replica_install and \
not options.domain_level > DOMAIN_LEVEL_0) or \
(options._replica_install and options.replica_file is not None):
if (options.no_pkinit or options.pkinit_cert_files is not None or
options.pkinit_pin is not None):
ansible_module.fail_json(
msg="pkinit on domain level 0 is not supported. Please "
"don't use any pkinit-related options.")
options.no_pkinit = True
"""
# pylint: enable=pointless-string-statement
if options.setup_dns:
if len(options.forwarders) < 1 and not options.no_forwarders and \
not options.auto_forwarders:
ansible_module.fail_json(
msg="You must specify at least one of forwarders, "
"auto-forwarders or no-forwarders")
if NUM_VERSION >= 40200 and options.master_password and \
not options.external_cert_files:
ansible_module.warn(
"Specifying kerberos master-password is deprecated")
options._installation_cleanup = True
if not options.external_ca and not options.external_cert_files and \
is_ipa_configured():
options._installation_cleanup = False
ansible_module.log(
"IPA server is already configured on this system. If you want "
"to reinstall the IPA server, please uninstall it first.")
ansible_module.exit_json(changed=False,
server_already_configured=True)
client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
if client_fstore.has_files():
options._installation_cleanup = False
ansible_module.log(
"IPA client is already configured on this system. "
"Please uninstall it before configuring the IPA server.")
ansible_module.exit_json(changed=False,
client_already_configured=True)
# validate reverse_zones
if not options.allow_zone_overlap:
for zone in options.reverse_zones:
with redirect_stdout(ansible_log):
check_zone_overlap(zone)
# validate zonemgr
if options.zonemgr:
if six.PY3:
with redirect_stdout(ansible_log):
bindinstance.validate_zonemgr_str(options.zonemgr)
else:
try:
# IDNA support requires unicode
encoding = getattr(sys.stdin, 'encoding', None)
if encoding is None:
encoding = 'utf-8'
value = options.zonemgr
if not isinstance(value, unicode):
value = options.zonemgr.decode(encoding)
else:
value = options.zonemgr
with redirect_stdout(ansible_log):
bindinstance.validate_zonemgr_str(value)
except ValueError as e:
# FIXME we can do this in better way
# https://fedorahosted.org/freeipa/ticket/4804
# decode to proper stderr encoding
stderr_encoding = getattr(sys.stderr, 'encoding', None)
if stderr_encoding is None:
stderr_encoding = 'utf-8'
error = unicode(e).encode(stderr_encoding)
ansible_module.fail_json(msg=error)
# external cert file paths are absolute
if options.external_cert_files:
for path in options.external_cert_files:
if not os.path.isabs(path):
ansible_module.fail_json(
msg="External cert file '%s' must use an absolute "
"path" % path)
options.setup_ca = True
# We only set up the CA if the PKCS#12 options are not given.
if options.dirsrv_cert_files and len(options.dirsrv_cert_files) > 0:
options.setup_ca = False
else:
options.setup_ca = True
if not options.setup_ca and options.ca_subject:
ansible_module.fail_json(
msg="--ca-subject cannot be used with CA-less installation")
if not options.setup_ca and options.subject_base:
ansible_module.fail_json(
msg="--subject-base cannot be used with CA-less installation")
if not options.setup_ca and options.setup_kra:
ansible_module.fail_json(
msg="--setup-kra cannot be used with CA-less installation")
# This will override any settings passed in on the cmdline
if os.path.isfile(paths.ROOT_IPA_CACHE):
# dm_password check removed, checked already
try:
cache_vars = read_cache(options.dm_password)
options.__dict__.update(cache_vars)
if cache_vars.get('external_ca', False):
options.external_ca = False
options.interactive = False
except Exception as e:
ansible_module.fail_json(
msg="Cannot process the cache file: %s" % str(e))
# ca_subject
if options.ca_subject:
ca.subject_validator(ca.VALID_SUBJECT_ATTRS, options.ca_subject)
# Memory check
if not options.skip_mem_check and check_available_memory is not None:
check_available_memory(ca=options.dirsrv_cert_files and
len(options.dirsrv_cert_files) > 0)
# IPv6 and SELinux check
tasks.check_ipv6_stack_enabled()
tasks.check_selinux_status()
if check_ldap_conf is not None:
check_ldap_conf()
_installation_cleanup = True
if not options.external_ca and not options.external_cert_files and \
is_ipa_configured():
_installation_cleanup = False
ansible_module.fail_json(
msg="IPA server is already configured on this system.")
if not options.no_ntp:
try:
timeconf.check_timedate_services()
except timeconf.NTPConflictingService as e:
ansible_module.log(
"WARNING: conflicting time&date synchronization service "
"'%s' will be disabled in favor of chronyd" %
e.conflicting_service)
except timeconf.NTPConfigurationError:
pass
if hasattr(httpinstance, "httpd_443_configured"):
# Check to see if httpd is already configured to listen on 443
if httpinstance.httpd_443_configured():
ansible_module.fail_json(
msg="httpd is already configured to listen on 443.")
if not options.external_cert_files:
# Make sure the 389-ds ports are available
try:
check_dirsrv(True)
except ScriptError as e:
ansible_module.fail_json(msg=e)
# check bind packages are installed
if options.setup_dns:
# Don't require an external DNS to say who we are if we are
# setting up a local DNS server.
options.no_host_dns = True
# host name
if options.host_name:
host_default = options.host_name
else:
host_default = get_fqdn()
try:
verify_fqdn(host_default, options.no_host_dns)
host_name = host_default
except BadHostError as e:
ansible_module.fail_json(msg=e)
host_name = host_name.lower()
if not options.domain_name:
domain_name = host_name[host_name.find(".") + 1:]
try:
validate_domain_name(domain_name)
except ValueError as e:
ansible_module.fail_json(
msg="Invalid domain name: %s" % unicode(e))
else:
domain_name = options.domain_name
domain_name = domain_name.lower()
# Both host_name and domain_name are lowercase at this point.
if host_name == domain_name:
ansible_module.fail_json(
msg="hostname cannot be the same as the domain name")
if not options.realm_name:
realm_name = domain_name.upper()
else:
realm_name = options.realm_name.upper()
# pylint: disable=deprecated-method
argspec = getargspec(validate_domain_name)
# pylint: enable=deprecated-method
if "entity" in argspec.args:
# NUM_VERSION >= 40690:
try:
validate_domain_name(realm_name, entity="realm")
except ValueError as e:
raise ScriptError("Invalid realm name: {0}".format(unicode(e)))
if not options.setup_adtrust:
# If domain name and realm does not match, IPA server will not be able
# to establish trust with Active Directory. Fail.
if domain_name.upper() != realm_name:
ansible_module.warn(
"Realm name does not match the domain name: "
"You will not be able to establish trusts with Active "
"Directory.")
# Do not ask for time source
# if not options.no_ntp and not options.unattended and not (
# options.ntp_servers or options.ntp_pool):
# options.ntp_servers, options.ntp_pool = timeconf.get_time_source()
#########################################################################
http_pkcs12_file = None
http_pkcs12_info = None
http_ca_cert = None
dirsrv_pkcs12_file = None
dirsrv_pkcs12_info = None
dirsrv_ca_cert = None
pkinit_pkcs12_file = None
pkinit_pkcs12_info = None
pkinit_ca_cert = None
if options.http_cert_files:
if options.http_pin is None:
ansible_module.fail_json(
msg="Apache Server private key unlock password required")
http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12(
cert_files=options.http_cert_files,
key_password=options.http_pin,
key_nickname=options.http_cert_name,
ca_cert_files=options.ca_cert_files,
host_name=host_name)
http_pkcs12_info = (http_pkcs12_file.name, http_pin)
if options.dirsrv_cert_files:
if options.dirsrv_pin is None:
ansible_module.fail_json(
msg="Directory Server private key unlock password required")
dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12(
cert_files=options.dirsrv_cert_files,
key_password=options.dirsrv_pin,
key_nickname=options.dirsrv_cert_name,
ca_cert_files=options.ca_cert_files,
host_name=host_name)
dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin)
if options.pkinit_cert_files:
if options.pkinit_pin is None:
ansible_module.fail_json(
msg="Kerberos KDC private key unlock password required")
pkinit_pkcs12_file, pkinit_pin, pkinit_ca_cert = load_pkcs12(
cert_files=options.pkinit_cert_files,
key_password=options.pkinit_pin,
key_nickname=options.pkinit_cert_name,
ca_cert_files=options.ca_cert_files,
realm_name=realm_name)
pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin)
if options.http_cert_files and options.dirsrv_cert_files and \
http_ca_cert != dirsrv_ca_cert:
ansible_module.fail_json(
msg="Apache Server SSL certificate and Directory Server SSL "
"certificate are not signed by the same CA certificate")
if options.http_cert_files and options.pkinit_cert_files and \
http_ca_cert != pkinit_ca_cert:
ansible_module.fail_json(
msg="Apache Server SSL certificate and PKINIT KDC "
"certificate are not signed by the same CA certificate")
# done ##################################################################
# Copy pkcs12_files to make them persistent till deployment is done
# and encode certificates for ansible compatibility
if http_pkcs12_info is not None:
copyfile(http_pkcs12_file.name, "/etc/ipa/.tmp_pkcs12_http")
http_pkcs12_info = ("/etc/ipa/.tmp_pkcs12_http", http_pin)
http_ca_cert = encode_certificate(http_ca_cert)
if dirsrv_pkcs12_info is not None:
copyfile(dirsrv_pkcs12_file.name, "/etc/ipa/.tmp_pkcs12_dirsrv")
dirsrv_pkcs12_info = ("/etc/ipa/.tmp_pkcs12_dirsrv", dirsrv_pin)
dirsrv_ca_cert = encode_certificate(dirsrv_ca_cert)
if pkinit_pkcs12_info is not None:
copyfile(pkinit_pkcs12_file.name, "/etc/ipa/.tmp_pkcs12_pkinit")
pkinit_pkcs12_info = ("/etc/ipa/.tmp_pkcs12_pkinit", pkinit_pin)
pkinit_ca_cert = encode_certificate(pkinit_ca_cert)
ansible_module.exit_json(
changed=False,
ipa_python_version=IPA_PYTHON_VERSION,
# basic
domain=domain_name,
realm=realm_name,
hostname=host_name,
_hostname_overridden=bool(options.host_name),
no_host_dns=options.no_host_dns,
# server
setup_adtrust=options.setup_adtrust,
setup_kra=options.setup_kra,
setup_ca=options.setup_ca,
idstart=options.idstart,
idmax=options.idmax,
no_pkinit=options.no_pkinit,
# ssl certificate
_dirsrv_pkcs12_info=dirsrv_pkcs12_info,
_dirsrv_ca_cert=dirsrv_ca_cert,
_http_pkcs12_info=http_pkcs12_info,
_http_ca_cert=http_ca_cert,
_pkinit_pkcs12_info=pkinit_pkcs12_info,
_pkinit_ca_cert=pkinit_ca_cert,
# certificate system
external_ca=options.external_ca,
external_ca_type=options.external_ca_type,
external_ca_profile=options.external_ca_profile,
# ad trust
rid_base=options.rid_base,
secondary_rid_base=options.secondary_rid_base,
# client
ntp_servers=options.ntp_servers,
ntp_pool=options.ntp_pool,
# additional
_installation_cleanup=_installation_cleanup,
domainlevel=options.domainlevel,
sid_generation_always=sid_generation_always,
random_serial_numbers=options._random_serial_numbers,
)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipaserver/meta/ 0000775 0000000 0000000 00000000000 14600563364 0021456 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaserver/meta/main.yml 0000664 0000000 0000000 00000000522 14600563364 0023124 0 ustar 00root root 0000000 0000000 ---
dependencies: []
galaxy_info:
author: Thomas Woerner
description: A role to setup an iPA domain server
company: Red Hat, Inc
license: GPLv3
min_ansible_version: "2.13"
platforms:
- name: Fedora
versions:
- all
- name: EL
versions:
- "7"
- "8"
galaxy_tags:
- identity
- ipa
- freeipa
ansible-freeipa-master/roles/ipaserver/module_utils/ 0000775 0000000 0000000 00000000000 14600563364 0023235 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaserver/module_utils/ansible_ipa_server.py 0000664 0000000 0000000 00000037007 14600563364 0027452 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-server-install code
#
# Copyright (C) 2017-2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type # pylint: disable=invalid-name
__all__ = ["IPAChangeConf", "certmonger", "sysrestore", "root_logger",
"ipa_generate_password", "run", "ScriptError", "services",
"tasks", "errors", "x509", "DOMAIN_LEVEL_0", "MIN_DOMAIN_LEVEL",
"MAX_DOMAIN_LEVEL", "validate_domain_name",
"no_matching_interface_for_ip_address_warning",
"check_zone_overlap", "timeconf", "ntpinstance", "adtrust",
"bindinstance", "ca", "dns", "httpinstance", "installutils",
"kra", "krbinstance", "otpdinstance", "custodiainstance",
"replication", "service", "sysupgrade", "IPA_MODULES",
"BadHostError", "get_fqdn", "get_server_ip_address",
"is_ipa_configured", "load_pkcs12", "read_password", "verify_fqdn",
"update_hosts_file", "check_dirsrv", "validate_admin_password",
"validate_dm_password", "read_cache", "write_cache",
"adtrustinstance", "IPAAPI_USER", "sync_time", "PKIIniLoader",
"default_subject_base", "default_ca_subject_dn",
"check_ldap_conf", "encode_certificate", "decode_certificate",
"check_available_memory", "getargspec", "get_min_idstart",
"paths", "api", "ipautil", "adtrust_imported", "NUM_VERSION",
"time_service", "kra_imported", "dsinstance", "IPA_PYTHON_VERSION",
"NUM_VERSION", "SerialNumber"]
import sys
import logging
# Import getargspec from inspect or provide own getargspec for
# Python 2 compatibility with Python 3.11+.
try:
from inspect import getargspec
except ImportError:
from collections import namedtuple
from inspect import getfullargspec
# The code is copied from Python 3.10 inspect.py
# Authors: Ka-Ping Yee
# Yury Selivanov
ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults')
def getargspec(func):
args, varargs, varkw, defaults, kwonlyargs, _kwonlydefaults, \
ann = getfullargspec(func)
if kwonlyargs or ann:
raise ValueError(
"Function has keyword-only parameters or annotations"
", use inspect.signature() API which can support them")
return ArgSpec(args, varargs, varkw, defaults)
try:
from contextlib import contextmanager as contextlib_contextmanager
from ansible.module_utils import six
import base64
from ipapython.version import NUM_VERSION, VERSION
if NUM_VERSION < 30201:
# See ipapython/version.py
IPA_MAJOR, IPA_MINOR, IPA_RELEASE = [int(x) for x in
VERSION.split(".", 2)]
IPA_PYTHON_VERSION = IPA_MAJOR * 10000 + IPA_MINOR * 100 + IPA_RELEASE
else:
IPA_PYTHON_VERSION = NUM_VERSION
if NUM_VERSION >= 40500:
# IPA version >= 4.5
from ipaclient.install.ipachangeconf import IPAChangeConf
from ipalib.install import certmonger
try:
from ipalib import sysrestore
except ImportError:
from ipalib.install import sysrestore
from ipapython import ipautil
from ipapython.ipa_log_manager import standard_logging_setup
try:
from ipapython.ipa_log_manager import root_logger
except ImportError:
root_logger = None
from ipapython.ipautil import (
ipa_generate_password, run)
from ipapython.admintool import ScriptError
from ipaplatform import services
from ipaplatform.paths import paths
from ipaplatform.tasks import tasks
from ipalib import api, errors, x509
from ipalib.constants import DOMAIN_LEVEL_0, MIN_DOMAIN_LEVEL, \
MAX_DOMAIN_LEVEL
try:
from ipalib.constants import IPAAPI_USER
except ImportError:
IPAAPI_USER = None
from ipalib.util import (
validate_domain_name,
no_matching_interface_for_ip_address_warning,
)
from ipapython.dnsutil import check_zone_overlap
from ipapython.dn import DN
try:
from ipaclient.install import timeconf
from ipaclient.install.client import sync_time
time_service = "chronyd" # pylint: disable=invalid-name
ntpinstance = None # pylint: disable=invalid-name
except ImportError:
try:
from ipaclient.install import ntpconf as timeconf
except ImportError:
from ipaclient import ntpconf as timeconf
from ipaserver.install import ntpinstance
time_service = "ntpd" # pylint: disable=invalid-name
sync_time = None # pylint: disable=invalid-name
from ipaserver.install import (
adtrust, bindinstance, ca, dns, dsinstance,
httpinstance, installutils, kra, krbinstance,
otpdinstance, custodiainstance, replication, service,
sysupgrade)
adtrust_imported = True # pylint: disable=invalid-name
kra_imported = True # pylint: disable=invalid-name
from ipaserver.install.installutils import (
BadHostError, get_fqdn, get_server_ip_address,
load_pkcs12, read_password, verify_fqdn,
update_hosts_file)
try:
from ipalib.facts import is_ipa_configured
except ImportError:
from ipaserver.install.installutils import is_ipa_configured
from ipaserver.install.server.install import (
check_dirsrv, validate_admin_password, validate_dm_password,
read_cache, write_cache)
try:
from ipaserver.install.dogtaginstance import PKIIniLoader
except ImportError:
PKIIniLoader = None
try:
from ipaserver.install.installutils import default_subject_base
except ImportError:
def default_subject_base(realm_name):
return DN(('O', realm_name))
try:
from ipalib.facts import IPA_MODULES
except ImportError:
from ipaserver.install.installutils import IPA_MODULES
try:
from ipaserver.install.installutils import default_ca_subject_dn
except ImportError:
def default_ca_subject_dn(subject_base):
return DN(('CN', 'Certificate Authority'), subject_base)
try:
from ipaserver.install.installutils import check_available_memory
except ImportError:
check_available_memory = None
try:
from ipaserver.install import adtrustinstance
_server_trust_ad_installed = True # pylint: disable=invalid-name
except ImportError:
_server_trust_ad_installed = False # pylint: disable=invalid-name
try:
from ipaclient.install.client import check_ldap_conf
except ImportError:
check_ldap_conf = None
try:
from ipalib.x509 import Encoding
except ImportError:
from cryptography.hazmat.primitives.serialization import Encoding
try:
from ipalib.x509 import load_pem_x509_certificate
certificate_loader = load_pem_x509_certificate
except ImportError:
from ipalib.x509 import load_certificate
certificate_loader = load_certificate
try:
from ipaserver.install.server.install import get_min_idstart
except ImportError:
get_min_idstart = None
# SerialNumber is defined in versions 4.10 and later and is
# used by Random Serian Number v3.
try:
from ipalib.parameters import SerialNumber
except ImportError:
SerialNumber = None
else:
# IPA version < 4.5
raise RuntimeError("freeipa version '%s' is too old" % VERSION)
except ImportError as _err:
ANSIBLE_IPA_SERVER_MODULE_IMPORT_ERROR = str(_err)
for attr in __all__:
setattr(sys.modules[__name__], attr, None)
else:
ANSIBLE_IPA_SERVER_MODULE_IMPORT_ERROR = None
logger = logging.getLogger("ipa-server-install")
def setup_logging():
# logger.setLevel(logging.DEBUG)
standard_logging_setup(
paths.IPASERVER_INSTALL_LOG, verbose=False, debug=False,
filemode='a', console_format='%(message)s')
@contextlib_contextmanager
def redirect_stdout(stream):
sys.stdout = stream
try:
yield stream
finally:
sys.stdout = sys.__stdout__
class AnsibleModuleLog():
def __init__(self, module):
self.module = module
_ansible_module_log = self
class AnsibleLoggingHandler(logging.Handler):
def emit(self, record):
_ansible_module_log.write(self.format(record))
self.logging_handler = AnsibleLoggingHandler()
logger.setLevel(logging.DEBUG)
logger.root.addHandler(self.logging_handler)
def close(self):
self.flush()
def flush(self):
pass
def log(self, msg):
# self.write(msg+"\n")
self.write(msg)
def debug(self, msg):
self.module.debug(msg)
def info(self, msg):
self.module.debug(msg)
@staticmethod
def isatty():
return False
def write(self, msg):
self.module.debug(msg)
# self.module.warn(msg)
# pylint: disable=too-few-public-methods, useless-object-inheritance
# pylint: disable=too-many-instance-attributes
class options_obj(object): # pylint: disable=invalid-name
def __init__(self):
self._replica_install = False
self.dnssec_master = False # future unknown
self.disable_dnssec_master = False # future unknown
self.domainlevel = MAX_DOMAIN_LEVEL # deprecated
self.domain_level = self.domainlevel # deprecated
self.interactive = False
self.unattended = not self.interactive
# def __getattribute__(self, attr):
# logger.info(" <-- Accessing options.%s" % attr)
# return super(options_obj, self).__getattribute__(attr)
# def __getattr__(self, attr):
# logger.info(" --> Adding missing options.%s" % attr)
# setattr(self, attr, None)
# return getattr(self, attr)
def knobs(self):
for name in self.__dict__:
yield self, name
# pylint: enable=too-few-public-methods, useless-object-inheritance
# pylint: enable=too-many-instance-attributes
options = options_obj()
installer = options
# pylint: disable=attribute-defined-outside-init
# ServerMasterInstall
options.add_sids = True
options.add_agents = False
# Installable
options.uninstalling = False
# ServerInstallInterface
options.description = "Server"
options.kinit_attempts = 1
options.fixed_primary = True
options.permit = False
options.enable_dns_updates = False
options.no_krb5_offline_passwords = False
options.preserve_sssd = False
options.no_sssd = False
# ServerMasterInstall
options.force_join = False
options.servers = None
options.no_wait_for_dns = True
options.host_password = None
options.keytab = None
options.setup_ca = True
# always run sidgen task and do not allow adding agents on first master
options.add_sids = True
options.add_agents = False
# ADTrustInstallInterface
# no_msdcs is deprecated
options.no_msdcs = False
# For pylint
options.external_cert_files = None
options.dirsrv_cert_files = None
# Uninstall
options.ignore_topology_disconnect = False
options.ignore_last_of_role = False
# pylint: enable=attribute-defined-outside-init
# pylint: disable=invalid-name
def api_Backend_ldap2(host_name, setup_ca, connect=False):
# we are sure we have the configuration file ready.
cfg = dict(context='installer', confdir=paths.ETC_IPA, in_server=True,
host=host_name)
if setup_ca:
# we have an IPA-integrated CA
cfg['ca_host'] = host_name
api.bootstrap(**cfg)
api.finalize()
if connect:
api.Backend.ldap2.connect()
# pylint: enable=invalid-name
def ds_init_info(ansible_log, fstore, domainlevel, dirsrv_config_file,
realm_name, host_name, domain_name, dm_password,
idstart, idmax, subject_base, ca_subject,
_no_hbac_allow, dirsrv_pkcs12_info, no_pkinit):
if not options.external_cert_files:
_ds = dsinstance.DsInstance(fstore=fstore, domainlevel=domainlevel,
config_ldif=dirsrv_config_file)
_ds.set_output(ansible_log)
if options.dirsrv_cert_files:
_dirsrv_pkcs12_info = dirsrv_pkcs12_info
else:
_dirsrv_pkcs12_info = None
with redirect_stdout(ansible_log):
_ds.init_info(realm_name, host_name, domain_name, dm_password,
subject_base, ca_subject, idstart, idmax,
# hbac_allow=not no_hbac_allow,
_dirsrv_pkcs12_info, setup_pkinit=not no_pkinit)
else:
_ds = dsinstance.DsInstance(fstore=fstore, domainlevel=domainlevel)
_ds.set_output(ansible_log)
with redirect_stdout(ansible_log):
_ds.init_info(realm_name, host_name, domain_name, dm_password,
subject_base, ca_subject, 1101, 1100, None,
setup_pkinit=not no_pkinit)
return _ds
def ansible_module_get_parsed_ip_addresses(ansible_module,
param='ip_addresses'):
ip_addrs = []
for _ip in ansible_module.params.get(param):
try:
ip_parsed = ipautil.CheckedIPAddress(_ip)
except Exception as err:
ansible_module.fail_json(
msg="Invalid IP Address %s: %s" % (_ip, err))
ip_addrs.append(ip_parsed)
return ip_addrs
def encode_certificate(cert):
"""
Encode a certificate using base64.
It also takes FreeIPA and Python versions into account.
"""
if isinstance(cert, (str, bytes)):
encoded = base64.b64encode(cert)
else:
encoded = base64.b64encode(cert.public_bytes(Encoding.DER))
if not six.PY2:
encoded = encoded.decode('ascii')
return encoded
def decode_certificate(cert):
"""
Decode a certificate using base64.
It also takes FreeIPA versions into account and returns a
IPACertificate for newer IPA versions.
"""
if hasattr(x509, "IPACertificate"):
cert = cert.strip()
if not cert.startswith("-----BEGIN CERTIFICATE-----"):
cert = "-----BEGIN CERTIFICATE-----\n" + cert
if not cert.endswith("-----END CERTIFICATE-----"):
cert += "\n-----END CERTIFICATE-----"
cert = certificate_loader(cert.encode('utf-8'))
else:
cert = base64.b64decode(cert)
return cert
def check_imports(module):
if ANSIBLE_IPA_SERVER_MODULE_IMPORT_ERROR is not None:
module.fail_json(msg=ANSIBLE_IPA_SERVER_MODULE_IMPORT_ERROR)
ansible-freeipa-master/roles/ipaserver/tasks/ 0000775 0000000 0000000 00000000000 14600563364 0021655 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaserver/tasks/copy_external_cert.yml 0000664 0000000 0000000 00000001344 14600563364 0026273 0 ustar 00root root 0000000 0000000 ---
- name: Copy external certificates
vars:
__item_basename: "{{ item | basename }}"
block:
- name: Install - Initialize ipaserver_external_cert_files
ansible.builtin.set_fact:
ipaserver_external_cert_files: []
when: ipaserver_external_cert_files is undefined
- name: Install - Copy "{{ item + " " + inventory_hostname + ':/root/' + __item_basename }}"
ansible.builtin.copy:
src: "{{ item }}"
dest: "/root/{{ __item_basename }}"
mode: preserve
force: yes
- name: Install - Extend ipaserver_external_cert_files with "/root/{{ __item_basename }}"
ansible.builtin.set_fact:
ipaserver_external_cert_files: "{{ ipaserver_external_cert_files + ['/root/' + (__item_basename)] }}"
ansible-freeipa-master/roles/ipaserver/tasks/install.yml 0000664 0000000 0000000 00000054167 14600563364 0024063 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipaserver
- name: Install - Package installation
when: ipaserver_install_packages | bool
block:
- name: Install - Ensure that IPA server packages are installed
ansible.builtin.package:
name: "{{ ipaserver_packages }}"
state: present
- name: Install - Ensure that IPA server packages for dns are installed
ansible.builtin.package:
name: "{{ ipaserver_packages_dns }}"
state: present
when: ipaserver_setup_dns | bool
- name: Install - Ensure that IPA server packages for adtrust are installed
ansible.builtin.package:
name: "{{ ipaserver_packages_adtrust }}"
state: present
when: ipaserver_setup_adtrust | bool
- name: Install - Ensure that firewall packages installed
ansible.builtin.package:
name: "{{ ipaserver_packages_firewalld }}"
state: present
when: ipaserver_setup_firewalld | bool
- name: Install - Firewall configuration
when: ipaserver_setup_firewalld | bool
block:
- name: Firewalld service - Ensure that firewalld is running
ansible.builtin.systemd:
name: firewalld
enabled: yes
state: started
- name: Firewalld - Verify runtime zone "{{ ipaserver_firewalld_zone }}"
ansible.builtin.shell: >
firewall-cmd
--info-zone="{{ ipaserver_firewalld_zone }}"
>/dev/null
when: ipaserver_firewalld_zone is defined
- name: Firewalld - Verify permanent zone "{{ ipaserver_firewalld_zone }}"
ansible.builtin.shell: >
firewall-cmd
--permanent
--info-zone="{{ ipaserver_firewalld_zone }}"
>/dev/null
when: ipaserver_firewalld_zone is defined
- name: Copy external certs
ansible.builtin.include_tasks: "{{ role_path }}/tasks/copy_external_cert.yml"
with_items: "{{ ipaserver_external_cert_files_from_controller }}"
when: ipaserver_external_cert_files_from_controller is defined and
ipaserver_external_cert_files_from_controller|length > 0 and
not ipaserver_external_cert_files is defined
- name: Install - Server installation test
ipaserver_test:
### basic ###
dm_password: "{{ ipadm_password }}"
password: "{{ ipaadmin_password }}"
master_password: "{{ ipaserver_master_password | default(omit) }}"
domain: "{{ ipaserver_domain | default(omit) }}"
realm: "{{ ipaserver_realm | default(omit) }}"
hostname: "{{ ipaserver_hostname | default(ansible_facts['fqdn']) }}"
ca_cert_files: "{{ ipaserver_ca_cert_files | default(omit) }}"
no_host_dns: "{{ ipaserver_no_host_dns }}"
pki_config_override: "{{ ipaserver_pki_config_override | default(omit) }}"
skip_mem_check: "{{ not ipaserver_mem_check }}"
### server ###
setup_adtrust: "{{ ipaserver_setup_adtrust }}"
setup_kra: "{{ ipaserver_setup_kra }}"
setup_dns: "{{ ipaserver_setup_dns }}"
idstart: "{{ ipaserver_idstart | default(omit) }}"
idmax: "{{ ipaserver_idmax | default(omit) }}"
# no_hbac_allow: "{{ ipaserver_no_hbac_allow }}"
no_pkinit: "{{ ipaserver_no_pkinit }}"
# no_ui_redirect: "{{ ipaserver_no_ui_redirect }}"
dirsrv_config_file: "{{ ipaserver_dirsrv_config_file | default(omit) }}"
### ssl certificate ###
dirsrv_cert_files: "{{ ipaserver_dirsrv_cert_files | default(omit) }}"
dirsrv_cert_name: "{{ ipaserver_dirsrv_cert_name | default(omit) }}"
dirsrv_pin: "{{ ipaserver_dirsrv_pin | default(omit) }}"
http_cert_files: "{{ ipaserver_http_cert_files | default(omit) }}"
http_cert_name: "{{ ipaserver_http_cert_name | default(omit) }}"
http_pin: "{{ ipaserver_http_pin | default(omit) }}"
pkinit_cert_files: "{{ ipaserver_pkinit_cert_files | default(omit) }}"
pkinit_cert_name: "{{ ipaserver_pkinit_cert_name | default(omit) }}"
pkinit_pin: "{{ ipaserver_pkinit_pin | default(omit) }}"
### client ###
# mkhomedir
ntp_servers: "{{ ipaclient_ntp_servers | default(omit) }}"
ntp_pool: "{{ ipaclient_ntp_pool | default(omit) }}"
no_ntp: "{{ ipaclient_no_ntp }}"
# ssh_trust_dns
# no_ssh
# no_sshd
# no_dns_sshfp
### certificate system ###
external_ca: "{{ ipaserver_external_ca }}"
external_ca_type: "{{ ipaserver_external_ca_type | default(omit) }}"
external_ca_profile: "{{ ipaserver_external_ca_profile | default(omit) }}"
external_cert_files: "{{ ipaserver_external_cert_files | default(omit) }}"
subject_base: "{{ ipaserver_subject_base | default(omit) }}"
ca_subject: "{{ ipaserver_ca_subject | default(omit) }}"
random_serial_numbers: "{{ ipaserver_random_serial_numbers | default(omit) }}"
# ca_signing_algorithm
### dns ###
allow_zone_overlap: "{{ ipaserver_allow_zone_overlap }}"
reverse_zones: "{{ ipaserver_reverse_zones | default([]) }}"
no_reverse: "{{ ipaserver_no_reverse }}"
auto_reverse: "{{ ipaserver_auto_reverse }}"
zonemgr: "{{ ipaserver_zonemgr | default(omit) }}"
forwarders: "{{ ipaserver_forwarders | default([]) }}"
no_forwarders: "{{ ipaserver_no_forwarders }}"
auto_forwarders: "{{ ipaserver_auto_forwarders }}"
forward_policy: "{{ ipaserver_forward_policy | default(omit) }}"
no_dnssec_validation: "{{ ipaserver_no_dnssec_validation }}"
### ad trust ###
enable_compat: "{{ ipaserver_enable_compat }}"
netbios_name: "{{ ipaserver_netbios_name | default(omit) }}"
rid_base: "{{ ipaserver_rid_base | default(omit) }}"
secondary_rid_base: "{{ ipaserver_secondary_rid_base | default(omit) }}"
### additional ###
register: result_ipaserver_test
- name: Install - Deploy server
when: not ansible_check_mode and not
(not result_ipaserver_test.changed and
(result_ipaserver_test.client_already_configured is defined or
result_ipaserver_test.server_already_configured is defined))
block:
- name: Install - Obtain master password
when: ipaserver_master_password is undefined
block:
- name: Install - Master password creation
no_log: yes
ipaserver_master_password:
dm_password: "{{ ipadm_password }}"
master_password: "{{ ipaserver_master_password | default(omit) }}"
register: result_ipaserver_master_password
- name: Install - Use new master password
no_log: yes
ansible.builtin.set_fact:
__derived_master_password:
"{{ result_ipaserver_master_password.password }}"
- name: Use user defined master password, if provided
when: ipaserver_master_password is defined
no_log: yes
ansible.builtin.set_fact:
__derived_master_password: "{{ ipaserver_master_password }}"
- name: Install - Server preparation
ipaserver_prepare:
### basic ###
dm_password: "{{ ipadm_password }}"
password: "{{ ipaadmin_password }}"
ip_addresses: "{{ ipaserver_ip_addresses | default([]) }}"
domain: "{{ result_ipaserver_test.domain }}"
realm: "{{ result_ipaserver_test.realm }}"
hostname: "{{ result_ipaserver_test.hostname }}"
no_host_dns: "{{ result_ipaserver_test.no_host_dns }}"
### server ###
setup_adtrust: "{{ ipaserver_setup_adtrust }}"
setup_kra: "{{ ipaserver_setup_kra }}"
setup_dns: "{{ ipaserver_setup_dns }}"
### certificate system ###
external_ca: "{{ ipaserver_external_ca }}"
external_ca_type: "{{ ipaserver_external_ca_type | default(omit) }}"
external_ca_profile:
"{{ ipaserver_external_ca_profile | default(omit) }}"
external_cert_files:
"{{ ipaserver_external_cert_files | default(omit) }}"
subject_base: "{{ ipaserver_subject_base | default(omit) }}"
ca_subject: "{{ ipaserver_ca_subject | default(omit) }}"
### dns ###
allow_zone_overlap: "{{ ipaserver_allow_zone_overlap }}"
reverse_zones: "{{ ipaserver_reverse_zones | default([]) }}"
no_reverse: "{{ ipaserver_no_reverse }}"
auto_reverse: "{{ ipaserver_auto_reverse }}"
zonemgr: "{{ ipaserver_zonemgr | default(omit) }}"
forwarders: "{{ ipaserver_forwarders | default([]) }}"
no_forwarders: "{{ ipaserver_no_forwarders }}"
auto_forwarders: "{{ ipaserver_auto_forwarders }}"
forward_policy: "{{ ipaserver_forward_policy | default(omit) }}"
no_dnssec_validation: "{{ ipaserver_no_dnssec_validation }}"
### ad trust ###
enable_compat: "{{ ipaserver_enable_compat }}"
netbios_name: "{{ ipaserver_netbios_name | default(omit) }}"
rid_base: "{{ ipaserver_rid_base | default(omit) }}"
secondary_rid_base: "{{ ipaserver_secondary_rid_base | default(omit) }}"
### additional ###
setup_ca: "{{ result_ipaserver_test.setup_ca }}"
sid_generation_always: "{{ result_ipaserver_test.sid_generation_always }}"
random_serial_numbers: "{{ result_ipaserver_test.random_serial_numbers }}"
_hostname_overridden: "{{ result_ipaserver_test._hostname_overridden }}"
register: result_ipaserver_prepare
- name: Install - Setup NTP
ipaserver_setup_ntp:
ntp_servers: "{{ result_ipaserver_test.ntp_servers | default(omit) }}"
ntp_pool: "{{ result_ipaserver_test.ntp_pool | default(omit) }}"
when: not ipaclient_no_ntp | bool and (ipaserver_external_cert_files
is undefined or ipaserver_external_cert_files|length < 1)
- name: Install - Setup DS
ipaserver_setup_ds:
dm_password: "{{ ipadm_password }}"
password: "{{ ipaadmin_password }}"
# master_password: "{{ __derived_master_password }}"
domain: "{{ result_ipaserver_test.domain }}"
realm: "{{ result_ipaserver_test.realm | default(omit) }}"
hostname: "{{ result_ipaserver_test.hostname }}"
# ip_addresses: "{{ result_ipaserver_prepare.ip_addresses }}"
# reverse_zones: "{{ result_ipaserver_prepare.reverse_zones }}"
# setup_adtrust: "{{ result_ipaserver_test.setup_adtrust }}"
# setup_kra: "{{ result_ipaserver_test.setup_kra }}"
# setup_dns: "{{ ipaserver_setup_dns }}"
setup_ca: "{{ result_ipaserver_test.setup_ca }}"
# no_host_dns: "{{ result_ipaserver_test.no_host_dns }}"
dirsrv_config_file: "{{ ipaserver_dirsrv_config_file | default(omit) }}"
dirsrv_cert_files: "{{ ipaserver_dirsrv_cert_files | default(omit) }}"
_dirsrv_pkcs12_info: "{{ result_ipaserver_test._dirsrv_pkcs12_info if result_ipaserver_test._dirsrv_pkcs12_info != None else omit }}"
external_cert_files:
"{{ ipaserver_external_cert_files | default(omit) }}"
subject_base: "{{ result_ipaserver_prepare.subject_base }}"
ca_subject: "{{ result_ipaserver_prepare.ca_subject }}"
# no_reverse: "{{ ipaserver_no_reverse }}"
# auto_forwarders: "{{ ipaserver_auto_forwarders }}"
no_pkinit: "{{ result_ipaserver_test.no_pkinit }}"
no_hbac_allow: "{{ ipaserver_no_hbac_allow }}"
idstart: "{{ result_ipaserver_test.idstart }}"
idmax: "{{ result_ipaserver_test.idmax }}"
- name: Install - Setup KRB
ipaserver_setup_krb:
dm_password: "{{ ipadm_password }}"
password: "{{ ipaadmin_password }}"
master_password: "{{ __derived_master_password }}"
domain: "{{ result_ipaserver_test.domain }}"
realm: "{{ result_ipaserver_test.realm }}"
hostname: "{{ result_ipaserver_test.hostname }}"
# ip_addresses: "{{ result_ipaserver_prepare.ip_addresses }}"
reverse_zones: "{{ result_ipaserver_prepare.reverse_zones }}"
setup_adtrust: "{{ result_ipaserver_test.setup_adtrust }}"
setup_kra: "{{ result_ipaserver_test.setup_kra }}"
setup_dns: "{{ ipaserver_setup_dns }}"
setup_ca: "{{ result_ipaserver_test.setup_ca }}"
no_host_dns: "{{ result_ipaserver_test.no_host_dns }}"
external_cert_files:
"{{ ipaserver_external_cert_files | default(omit) }}"
subject_base: "{{ result_ipaserver_prepare.subject_base }}"
ca_subject: "{{ result_ipaserver_prepare.ca_subject }}"
no_reverse: "{{ ipaserver_no_reverse }}"
auto_forwarders: "{{ ipaserver_auto_forwarders }}"
no_pkinit: "{{ result_ipaserver_test.no_pkinit }}"
no_hbac_allow: "{{ ipaserver_no_hbac_allow }}"
idstart: "{{ result_ipaserver_test.idstart }}"
idmax: "{{ result_ipaserver_test.idmax }}"
_pkinit_pkcs12_info: "{{ result_ipaserver_test._pkinit_pkcs12_info if result_ipaserver_test._pkinit_pkcs12_info != None else omit }}"
- name: Install - Setup CA
ipaserver_setup_ca:
dm_password: "{{ ipadm_password }}"
password: "{{ ipaadmin_password }}"
master_password: "{{ __derived_master_password }}"
# ip_addresses: "{{ result_ipaserver_prepare.ip_addresses }}"
domain: "{{ result_ipaserver_test.domain }}"
realm: "{{ result_ipaserver_test.realm }}"
hostname: "{{ result_ipaserver_test.hostname }}"
no_host_dns: "{{ result_ipaserver_test.no_host_dns }}"
pki_config_override: "{{ ipaserver_pki_config_override |
default(omit) }}"
setup_adtrust: "{{ result_ipaserver_test.setup_adtrust }}"
setup_kra: "{{ result_ipaserver_test.setup_kra }}"
setup_dns: "{{ ipaserver_setup_dns }}"
setup_ca: "{{ result_ipaserver_test.setup_ca }}"
idstart: "{{ result_ipaserver_test.idstart }}"
idmax: "{{ result_ipaserver_test.idmax }}"
no_hbac_allow: "{{ ipaserver_no_hbac_allow }}"
no_pkinit: "{{ result_ipaserver_test.no_pkinit }}"
dirsrv_config_file: "{{ ipaserver_dirsrv_config_file | default(omit) }}"
dirsrv_cert_files: "{{ ipaserver_dirsrv_cert_files | default([]) }}"
_dirsrv_pkcs12_info: "{{ result_ipaserver_test._dirsrv_pkcs12_info if result_ipaserver_test._dirsrv_pkcs12_info != None else omit }}"
external_ca: "{{ ipaserver_external_ca }}"
external_ca_type: "{{ ipaserver_external_ca_type | default(omit) }}"
external_ca_profile:
"{{ ipaserver_external_ca_profile | default(omit) }}"
external_cert_files:
"{{ ipaserver_external_cert_files | default(omit) }}"
subject_base: "{{ result_ipaserver_prepare.subject_base }}"
_subject_base: "{{ result_ipaserver_prepare._subject_base }}"
ca_subject: "{{ result_ipaserver_prepare.ca_subject }}"
_ca_subject: "{{ result_ipaserver_prepare._ca_subject }}"
ca_signing_algorithm: "{{ ipaserver_ca_signing_algorithm |
default(omit) }}"
_random_serial_numbers: "{{ result_ipaserver_prepare._random_serial_numbers }}"
reverse_zones: "{{ result_ipaserver_prepare.reverse_zones }}"
no_reverse: "{{ ipaserver_no_reverse }}"
auto_forwarders: "{{ ipaserver_auto_forwarders }}"
_http_ca_cert: "{{ result_ipaserver_test._http_ca_cert }}"
register: result_ipaserver_setup_ca
- name: Copy /root/ipa.csr to "{{ inventory_hostname + '-ipa.csr' }}"
ansible.builtin.fetch:
src: /root/ipa.csr
dest: "{{ inventory_hostname }}-ipa.csr"
flat: yes
when: result_ipaserver_setup_ca.csr_generated | bool and
ipaserver_copy_csr_to_controller | bool
- name: Install - Configure services
when: not result_ipaserver_setup_ca.csr_generated | bool
block:
- name: Install - Setup otpd
ipaserver_setup_otpd:
realm: "{{ result_ipaserver_test.realm }}"
hostname: "{{ result_ipaserver_test.hostname }}"
setup_ca: "{{ result_ipaserver_test.setup_ca }}"
- name: Install - Setup HTTP
ipaserver_setup_http:
dm_password: "{{ ipadm_password }}"
password: "{{ ipaadmin_password }}"
master_password: "{{ __derived_master_password }}"
domain: "{{ result_ipaserver_test.domain }}"
realm: "{{ result_ipaserver_test.realm }}"
hostname: "{{ result_ipaserver_test.hostname }}"
# ip_addresses: "{{ result_ipaserver_prepare.ip_addresses }}"
reverse_zones: "{{ result_ipaserver_prepare.reverse_zones }}"
setup_adtrust: "{{ result_ipaserver_test.setup_adtrust }}"
setup_kra: "{{ result_ipaserver_test.setup_kra }}"
setup_dns: "{{ ipaserver_setup_dns }}"
setup_ca: "{{ result_ipaserver_test.setup_ca }}"
no_host_dns: "{{ result_ipaserver_test.no_host_dns }}"
dirsrv_cert_files: "{{ ipaserver_dirsrv_cert_files | default([]) }}"
external_cert_files:
"{{ ipaserver_external_cert_files | default(omit) }}"
subject_base: "{{ result_ipaserver_prepare.subject_base }}"
_subject_base: "{{ result_ipaserver_prepare._subject_base }}"
ca_subject: "{{ result_ipaserver_prepare.ca_subject }}"
_ca_subject: "{{ result_ipaserver_prepare._ca_subject }}"
no_reverse: "{{ ipaserver_no_reverse }}"
auto_forwarders: "{{ ipaserver_auto_forwarders }}"
no_pkinit: "{{ result_ipaserver_test.no_pkinit }}"
no_hbac_allow: "{{ ipaserver_no_hbac_allow }}"
idstart: "{{ result_ipaserver_test.idstart }}"
idmax: "{{ result_ipaserver_test.idmax }}"
http_cert_files: "{{ ipaserver_http_cert_files | default([]) }}"
no_ui_redirect: "{{ ipaserver_no_ui_redirect }}"
_http_pkcs12_info: "{{ result_ipaserver_test._http_pkcs12_info if result_ipaserver_test._http_pkcs12_info != None else omit }}"
- name: Install - Setup KRA
ipaserver_setup_kra:
hostname: "{{ result_ipaserver_test.hostname }}"
setup_ca: "{{ result_ipaserver_test.setup_ca }}"
dm_password: "{{ ipadm_password }}"
setup_kra: "{{ result_ipaserver_test.setup_kra }}"
realm: "{{ result_ipaserver_test.realm }}"
pki_config_override: "{{ ipaserver_pki_config_override |
default(omit) }}"
when: result_ipaserver_test.setup_kra | bool
- name: Install - Setup DNS
ipaserver_setup_dns:
ip_addresses: "{{ ipaserver_ip_addresses | default([]) }}"
domain: "{{ result_ipaserver_test.domain }}"
realm: "{{ result_ipaserver_test.realm }}"
hostname: "{{ result_ipaserver_test.hostname }}"
setup_ca: "{{ result_ipaserver_test.setup_ca }}"
setup_dns: "{{ ipaserver_setup_dns }}"
forwarders: "{{ result_ipaserver_prepare.forwarders }}"
forward_policy: "{{ result_ipaserver_prepare.forward_policy }}"
zonemgr: "{{ ipaserver_zonemgr | default(omit) }}"
no_dnssec_validation: "{{ result_ipaserver_prepare.no_dnssec_validation }}"
### additional ###
dns_ip_addresses: "{{ result_ipaserver_prepare.dns_ip_addresses }}"
dns_reverse_zones: "{{ result_ipaserver_prepare.dns_reverse_zones }}"
when: ipaserver_setup_dns | bool
- name: Install - Setup ADTRUST
ipaserver_setup_adtrust:
hostname: "{{ result_ipaserver_test.hostname }}"
setup_ca: "{{ result_ipaserver_test.setup_ca }}"
setup_adtrust: "{{ result_ipaserver_test.setup_adtrust }}"
### ad trust ###
enable_compat: "{{ ipaserver_enable_compat }}"
rid_base: "{{ result_ipaserver_test.rid_base }}"
secondary_rid_base: "{{ result_ipaserver_test.secondary_rid_base }}"
### additional ###
adtrust_netbios_name: "{{ result_ipaserver_prepare.adtrust_netbios_name }}"
adtrust_reset_netbios_name:
"{{ result_ipaserver_prepare.adtrust_reset_netbios_name }}"
when: result_ipaserver_test.setup_adtrust or
result_ipaserver_test.sid_generation_always
- name: Install - Set DS password
ipaserver_set_ds_password:
dm_password: "{{ ipadm_password }}"
password: "{{ ipaadmin_password }}"
domain: "{{ result_ipaserver_test.domain }}"
realm: "{{ result_ipaserver_test.realm }}"
hostname: "{{ result_ipaserver_test.hostname }}"
setup_ca: "{{ result_ipaserver_test.setup_ca }}"
subject_base: "{{ result_ipaserver_prepare.subject_base }}"
ca_subject: "{{ result_ipaserver_prepare.ca_subject }}"
no_pkinit: "{{ result_ipaserver_test.no_pkinit }}"
no_hbac_allow: "{{ ipaserver_no_hbac_allow }}"
idstart: "{{ result_ipaserver_test.idstart }}"
idmax: "{{ result_ipaserver_test.idmax }}"
dirsrv_config_file: "{{ ipaserver_dirsrv_config_file | default(omit) }}"
_dirsrv_pkcs12_info: "{{ result_ipaserver_test._dirsrv_pkcs12_info if result_ipaserver_test._dirsrv_pkcs12_info != None else omit }}"
- name: Install - Setup client
ansible.builtin.include_role:
name: ipaclient
vars:
state: present
ipaclient_on_master: yes
ipaclient_domain: "{{ result_ipaserver_test.domain }}"
ipaclient_realm: "{{ result_ipaserver_test.realm }}"
ipaclient_servers: ["{{ result_ipaserver_test.hostname }}"]
ipaclient_hostname: "{{ result_ipaserver_test.hostname }}"
ipaclient_no_ntp:
"{{ 'true' if result_ipaserver_test.ipa_python_version >= 40690
else 'false' }}"
ipaclient_install_packages: no
- name: Install - Enable IPA
ipaserver_enable_ipa:
hostname: "{{ result_ipaserver_test.hostname }}"
setup_dns: "{{ ipaserver_setup_dns }}"
setup_ca: "{{ result_ipaserver_test.setup_ca }}"
register: result_ipaserver_enable_ipa
- name: Install - Configure firewalld
ansible.builtin.command: >
firewall-cmd
--permanent
--zone="{{ ipaserver_firewalld_zone if ipaserver_firewalld_zone is
defined else '' }}"
--add-service=freeipa-ldap
--add-service=freeipa-ldaps
{{ "--add-service=freeipa-trust" if ipaserver_setup_adtrust | bool
else "" }}
{{ "--add-service=dns" if ipaserver_setup_dns | bool else "" }}
{{ "--add-service=ntp" if not ipaclient_no_ntp | bool else "" }}
when: ipaserver_setup_firewalld | bool
- name: Install - Configure firewalld runtime
ansible.builtin.command: >
firewall-cmd
--zone="{{ ipaserver_firewalld_zone if ipaserver_firewalld_zone is
defined else '' }}"
--add-service=freeipa-ldap
--add-service=freeipa-ldaps
{{ "--add-service=freeipa-trust" if ipaserver_setup_adtrust | bool
else "" }}
{{ "--add-service=dns" if ipaserver_setup_dns | bool else "" }}
{{ "--add-service=ntp" if not ipaclient_no_ntp | bool else "" }}
when: ipaserver_setup_firewalld | bool
always:
- name: Install - Cleanup root IPA cache
ansible.builtin.file:
path: "/root/.ipa_cache"
state: absent
- name: Cleanup temporary files
ansible.builtin.file:
path: "{{ item }}"
state: absent
with_items:
- "/etc/ipa/.tmp_pkcs12_dirsrv"
- "/etc/ipa/.tmp_pkcs12_http"
- "/etc/ipa/.tmp_pkcs12_pkinit"
ansible-freeipa-master/roles/ipaserver/tasks/main.yml 0000664 0000000 0000000 00000002273 14600563364 0023330 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipaserver
- name: Import variables specific to distribution
ansible.builtin.include_vars: "{{ item }}"
with_first_found:
- "vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_version'] }}.yml"
- "vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "vars/{{ ansible_facts['distribution'] }}.yml"
# os_family is used as a fallback for distros which are not currently
# supported, but are based on a supported distro family. For example,
# Oracle, Rocky, Alma and Alibaba linux, which are all "RedHat" based.
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_version'] }}.yml"
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "vars/{{ ansible_facts['os_family'] }}.yml"
# If neither distro nor family is supported, try a default configuration.
- "vars/default.yml"
- name: Install IPA server
ansible.builtin.include_tasks: install.yml
when: state|default('present') == 'present'
- name: Uninstall IPA server
ansible.builtin.include_tasks: uninstall.yml
when: state|default('present') == 'absent'
ansible-freeipa-master/roles/ipaserver/tasks/uninstall.yml 0000664 0000000 0000000 00000004677 14600563364 0024427 0 ustar 00root root 0000000 0000000 ---
# tasks to uninstall IPA server
- name: Uninstall - Set server hostname for removal
ansible.builtin.set_fact:
_remove_hostname: "{{ ansible_facts['fqdn'] }}"
- name: Uninstall - Remove server
when: ipaserver_remove_from_domain
block:
- name: Uninstall - Fail on missing ipaadmin_password for server removal
ansible.builtin.fail:
msg: "'ipaadmin_password' is needed for 'ipaserver_remove_from_domain'"
when: ipaadmin_password is not defined
- name: Uninstall - Fail on missing ipaserver_remove_on_server with ipaserver_ignore_topology_disconnect
ansible.builtin.fail:
msg: "'ipaserver_remove_on_server' is needed for 'ipaserver_remove_from_domain' with 'ipaserver_ignore_topology_disconnect'"
when: ipaserver_ignore_topology_disconnect | bool
and ipaserver_remove_on_server is not defined
- name: Uninstall - Get connected server
ipaserver_get_connected_server:
ipaadmin_principal: "{{ ipaadmin_principal | default('admin') }}"
ipaadmin_password: "{{ ipaadmin_password }}"
hostname: "{{ _remove_hostname }}"
register: result_get_connected_server
when: ipaserver_remove_on_server is not defined
# REMOVE SERVER FROM DOMAIN
- name: Uninstall - Server del "{{ _remove_hostname }}"
ipaserver:
ipaadmin_principal: "{{ ipaadmin_principal | default('admin') }}"
ipaadmin_password: "{{ ipaadmin_password }}"
name: "{{ _remove_hostname }}"
ignore_last_of_role: "{{ ipaserver_ignore_last_of_role }}"
ignore_topology_disconnect: "{{ ipaserver_ignore_topology_disconnect }}"
# delete_continue: "{{ ipaserver_delete_continue }}"
state: absent
delegate_to: "{{ ipaserver_remove_on_server | default(result_get_connected_server.server) }}"
when: ipaserver_remove_on_server is defined or
result_get_connected_server.server is defined
- name: Uninstall - Uninstall IPA server
ansible.builtin.command: >
/usr/sbin/ipa-server-install
--uninstall
-U
{{ '--ignore-topology-disconnect' if ipaserver_ignore_topology_disconnect
| bool else '' }}
{{ '--ignore-last-of-role' if ipaserver_ignore_last_of_role | bool else '' }}
register: uninstall
# 1 means that uninstall failed because IPA server was not configured
failed_when: uninstall.rc != 0 and uninstall.rc != 1
changed_when: uninstall.rc == 0
#- name: Remove IPA server packages
# ansible.builtin.package:
# name: "{{ ipaserver_packages }}"
# state: absent
ansible-freeipa-master/roles/ipaserver/vars/ 0000775 0000000 0000000 00000000000 14600563364 0021503 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipaserver/vars/Fedora-25.yml 0000664 0000000 0000000 00000000402 14600563364 0023646 0 ustar 00root root 0000000 0000000 # defaults file for ipaserver
# vars/Fedora-25.yml
---
ipaserver_packages: [ "ipa-server", "libselinux-python" ]
ipaserver_packages_dns: [ "ipa-server-dns" ]
ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipaserver/vars/Fedora-26.yml 0000664 0000000 0000000 00000000402 14600563364 0023647 0 ustar 00root root 0000000 0000000 # defaults file for ipaserver
# vars/Fedora-26.yml
---
ipaserver_packages: [ "ipa-server", "libselinux-python" ]
ipaserver_packages_dns: [ "ipa-server-dns" ]
ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipaserver/vars/Fedora-27.yml 0000664 0000000 0000000 00000000402 14600563364 0023650 0 ustar 00root root 0000000 0000000 # defaults file for ipaserver
# vars/Fedora-27.yml
---
ipaserver_packages: [ "ipa-server", "libselinux-python" ]
ipaserver_packages_dns: [ "ipa-server-dns" ]
ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipaserver/vars/Fedora.yml 0000664 0000000 0000000 00000000414 14600563364 0023425 0 ustar 00root root 0000000 0000000 # defaults file for ipaserver
# vars/Fedora.yml
---
ipaserver_packages: [ "freeipa-server", "python3-libselinux" ]
ipaserver_packages_dns: [ "freeipa-server-dns" ]
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipaserver/vars/RedHat-7.yml 0000664 0000000 0000000 00000000401 14600563364 0023534 0 ustar 00root root 0000000 0000000 # defaults file for ipaserver
# vars/RedHat-7.yml
---
ipaserver_packages: [ "ipa-server", "libselinux-python" ]
ipaserver_packages_dns: [ "ipa-server-dns" ]
ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipaserver/vars/RedHat-8.yml 0000664 0000000 0000000 00000000354 14600563364 0023544 0 ustar 00root root 0000000 0000000 # defaults file for ipaserver
# vars/RedHat-8.yml
---
ipaserver_packages: [ "@idm:DL1/server" ]
ipaserver_packages_dns: [ "@idm:DL1/dns" ]
ipaserver_packages_adtrust: [ "@idm:DL1/adtrust" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipaserver/vars/Ubuntu-18.04.yml 0000664 0000000 0000000 00000000674 14600563364 0024167 0 ustar 00root root 0000000 0000000 # vars/Ubuntu.yml
---
ipaserver_packages: [ "freeipa-server" ]
ipaserver_packages_dns: [ "freeipa-server-dns" ]
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
# Ubuntu Bionic Beaver must use python2 as Python interpreter due
# to the way python-ipalib package is defined.
# Package python2.7 must be installed before executing this role.
ansible_python_interpreter: '/usr/bin/python2.7'
ansible-freeipa-master/roles/ipaserver/vars/Ubuntu.yml 0000664 0000000 0000000 00000000366 14600563364 0023515 0 ustar 00root root 0000000 0000000 # defaults file for ipaserver
# vars/Ubuntu.yml
---
ipaserver_packages: [ "freeipa-server" ]
ipaserver_packages_dns: [ "freeipa-server-dns" ]
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipaserver/vars/default.yml 0000664 0000000 0000000 00000000405 14600563364 0023651 0 ustar 00root root 0000000 0000000 # defaults file for ipaserver
# vars/default.yml
---
ipaserver_packages: [ "ipa-server", "python3-libselinux" ]
ipaserver_packages_dns: [ "ipa-server-dns" ]
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
ipaserver_packages_firewalld: [ "firewalld" ]
ansible-freeipa-master/roles/ipasmartcard_client/ 0000775 0000000 0000000 00000000000 14600563364 0022540 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_client/README.md 0000664 0000000 0000000 00000005022 14600563364 0024016 0 ustar 00root root 0000000 0000000 ipasmartcard_client role
========================
Description
-----------
This role allows to configure IPA clients for Smart Card authentication.
**Note**: The ansible-freeipa smartcard client role requires an enrolled IPA client.
Features
--------
* Client setup for Smart Card authentication
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.5 and up are supported by this role.
Supported Distributions
-----------------------
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
* Supported distribution (needed for package installation only, see above)
* Enrolled IPA client
Limitations
-----------
Only the enablement of smartcards is supported by the role, there is no disablement.
Usage
=====
Example inventory file with IPA clients:
```ini
[ipaclients]
ipaclient1.example.com
ipaclient2.example.com
[ipaclients:vars]
ipaadmin_password=SomeADMINpassword
ipasmartcard_client_ca_certs=/etc/ipa/ca.crt
```
Example playbook to setup smartcard for the IPA clients using admin password and ipasmartcard_client_ca_certs from inventory file:
```yaml
---
- name: Playbook to setup smartcard for IPA clients
hosts: ipaclients
become: true
roles:
- role: ipasmartcard_client
state: present
```
Playbooks
=========
The playbooks needed to setup smartcard for the IPA clients is part of the repository in the playbooks folder.
```
install-smartcard-clients.yml
```
Please remember to link or copy the playbooks to the base directory of ansible-freeipa if you want to use the roles within the source archive.
How to setup smartcard for clients
----------------------------------
```bash
ansible-playbook -v -i inventory/hosts install-smartcard-clients.yml
```
This will setup the clients for smartcard use.
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The kerberos principal used for admin. Will be set to `admin` if not set. (string) | no
`ipaadmin_password` | The password for the IPA admin user. As an alternative an admin user keytab can be used instead with `ipaadmin_keytab`. (string) | yes
`ipaadmin_keytab` | The admin keytab as an alternative to `ipaadmin_password`. (string) | no
`ipasmartcard_client_ca_certs` | The CA certificates for smartcard use. If `ipasmartcard_client_ca_certs` is not set, but `ipasmartcard_server_ca_certs`, then `ipasmartcard_server_ca_certs` will be used. | yes
Authors
=======
Thomas Woerner
ansible-freeipa-master/roles/ipasmartcard_client/defaults/ 0000775 0000000 0000000 00000000000 14600563364 0024347 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_client/defaults/main.yml 0000664 0000000 0000000 00000000122 14600563364 0026011 0 ustar 00root root 0000000 0000000 ---
# defaults file for ipasmartcard_client role
ipaclient_install_packages: yes
ansible-freeipa-master/roles/ipasmartcard_client/files/ 0000775 0000000 0000000 00000000000 14600563364 0023642 5 ustar 00root root 0000000 0000000 ipasmartcard_client_add_ca_to_sssd_auth_ca_db.sh 0000664 0000000 0000000 00000001663 14600563364 0035277 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_client/files #!/bin/bash -eu
# Authors:
# Thomas Woerner
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
cert_file=$1
db=$2
if [ -z "${cert_file}" ] || [ -z "${db}" ]; then
echo "Usage: $0 "
exit 1
fi
cat "${cert_file}" >> "${db}"
ipasmartcard_client_add_ca_to_systemwide_db.sh 0000664 0000000 0000000 00000001763 14600563364 0035035 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_client/files #!/bin/bash -eu
# Authors:
# Thomas Woerner
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
cert_file=$1
db=$2
if [ -z "${cert_file}" ] || [ -z "${db}" ]; then
echo "Usage: $0 "
exit 1
fi
uuid=$(uuidgen)
certutil -d "${db}" -A -i "${cert_file}" -n "Smart Card CA ${uuid}" -t CT,C,C
ipasmartcard_client_add_pkcs11_module_to_systemwide_db.sh 0000664 0000000 0000000 00000002311 14600563364 0037107 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_client/files #!/bin/bash -eu
# Authors:
# Thomas Woerner
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
nssdb=$1
module_name="OpenSC"
pkcs11_shared_lib="/usr/lib64/opensc-pkcs11.so"
if [ -z "${nssdb}" ]; then
echo "Usage: $0 "
exit 1
fi
if modutil -dbdir "${nssdb}" -list | grep -q "${module_name}" || p11-kit list-modules | grep -i "${module_name}" -q
then
echo "${module_name} PKCS#11 module already configured"
else
echo "" | modutil -dbdir "${nssdb}" -add "${module_name}" -libfile "${pkcs11_shared_lib}"
fi
ansible-freeipa-master/roles/ipasmartcard_client/library/ 0000775 0000000 0000000 00000000000 14600563364 0024204 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_client/library/ipasmartcard_client_get_vars.py 0000664 0000000 0000000 00000004631 14600563364 0032464 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipasmartcard_client_get_vars
short_description:
Get variables from ipaplatform and python interpreter used for the module.
description:
Get variables from ipaplatform and python interpreter used for the module.
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
- name: Get VARS from IPA
ipasmartcard_client_get_vars:
register: ipasmartcard_client_vars
'''
RETURN = '''
NSS_DB_DIR:
description: paths.NSS_DB_DIR from ipaplatform
returned: always
type: str
USE_AUTHSELECT:
description: True if "AUTHSELECT" is defined in paths
returned: always
type: bool
python_interpreter:
description: Python interpreter from sys.executable
returned: always
type: str
'''
import sys
from ansible.module_utils.basic import AnsibleModule
try:
from ipaplatform.paths import paths
except ImportError as _err:
MODULE_IMPORT_ERROR = str(_err)
paths = None
else:
MODULE_IMPORT_ERROR = None
def main():
ansible_module = AnsibleModule(
argument_spec={},
supports_check_mode=False,
)
if MODULE_IMPORT_ERROR is not None:
ansible_module.fail_json(msg=MODULE_IMPORT_ERROR)
ansible_module.exit_json(changed=False,
NSS_DB_DIR=paths.NSS_DB_DIR,
USE_AUTHSELECT=hasattr(paths, "AUTHSELECT"),
python_interpreter=sys.executable)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipasmartcard_client/library/ipasmartcard_client_validate_ca_certs.py 0000664 0000000 0000000 00000006113 14600563364 0034303 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipasmartcard_client_validate_ca_certs
short_description: Validate CA certs
description: Validate CA certs
options:
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
type: list
elements: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os.path
from ansible.module_utils.basic import AnsibleModule
try:
from ipalib import x509
except ImportError:
x509 = None
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
ca_cert_files=dict(required=False, type='list', elements='str',
default=[]),
),
supports_check_mode=False,
)
# get parameters #
ca_cert_files = ansible_module.params.get('ca_cert_files')
# import check #
if x509 is None:
ansible_module.fail_json(msg="Failed to import x509 from ipalib")
# validate ca certs #
if ca_cert_files is not None:
if not isinstance(ca_cert_files, list):
ansible_module.fail_json(
msg="Expected list, got %s" % repr(ca_cert_files))
# remove duplicates
ca_cert_files = list(dict.fromkeys(ca_cert_files))
# validate
for cert in ca_cert_files:
if not os.path.exists(cert):
ansible_module.fail_json(msg="'%s' does not exist" % cert)
if not os.path.isfile(cert):
ansible_module.fail_json(msg="'%s' is not a file" % cert)
if not os.path.isabs(cert):
ansible_module.fail_json(
msg="'%s' is not an absolute file path" % cert)
try:
x509.load_certificate_from_file(cert)
except Exception:
ansible_module.fail_json(
msg="'%s' is not a valid certificate file" % cert)
# exit #
ansible_module.exit_json(changed=False,
ca_cert_files=ca_cert_files)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipasmartcard_client/meta/ 0000775 0000000 0000000 00000000000 14600563364 0023466 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_client/meta/main.yml 0000664 0000000 0000000 00000000571 14600563364 0025140 0 ustar 00root root 0000000 0000000 ---
dependencies: []
galaxy_info:
author: Thomas Woerner
description: A role to setup IPA server(s) for Smart Card authentication
company: Red Hat, Inc
license: GPLv3
min_ansible_version: "2.13"
platforms:
- name: Fedora
versions:
- all
- name: EL
versions:
- "7"
- "8"
galaxy_tags:
- identity
- ipa
- freeipa
- smartcard
ansible-freeipa-master/roles/ipasmartcard_client/tasks/ 0000775 0000000 0000000 00000000000 14600563364 0023665 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_client/tasks/main.yml 0000664 0000000 0000000 00000013711 14600563364 0025337 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipasmartcard_client role
- name: Uninstall smartcard client
ansible.builtin.fail:
msg: "Uninstalling smartcard for IPA is not supported"
when: state|default('present') == 'absent'
- name: Import variables specific to distribution
ansible.builtin.include_vars: "{{ item }}"
with_first_found:
- "vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_version'] }}.yml"
- "vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "vars/{{ ansible_facts['distribution'] }}.yml"
# os_family is used as a fallback for distros which are not currently
# supported, but are based on a supported distro family. For example,
# Oracle, Rocky, Alma and Alibaba linux, which are all "RedHat" based.
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_version'] }}.yml"
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "vars/{{ ansible_facts['os_family'] }}.yml"
# If neither distro nor family is supported, try a default configuration.
- "vars/default.yml"
- name: Client configuration
block:
# CA CERTS
# Use "ipasmartcard_server_ca_certs"
- name: Use "ipasmartcard_server_ca_certs"
ansible.builtin.set_fact:
ipasmartcard_client_ca_certs: "{{ ipasmartcard_server_ca_certs }}"
when: ipasmartcard_client_ca_certs is not defined and
ipasmartcard_server_ca_certs is defined
# Fail on empty "ipasmartcard_client_ca_certs"
- name: Fail on empty "ipasmartcard_client_ca_certs"
ansible.builtin.fail:
msg: "No CA certs given in 'ipasmartcard_client_ca_certs'"
when: ipasmartcard_client_ca_certs is not defined or
ipasmartcard_client_ca_certs | length < 1
# Validate ipasmartcard_client_ca_certs
- name: Validate CA certs "{{ ipasmartcard_client_ca_certs }}"
ipasmartcard_client_validate_ca_certs:
ca_cert_files: "{{ ipasmartcard_client_ca_certs }}"
register: result_validate_ca_certs
# INSTALL needed packages: opensc, dconf and krb5-pkinit-openssl
- name: Ensure needed packages are installed
ansible.builtin.package:
name: "{{ ipasmartcard_client_packages }}"
state: present
# REMOVE pam_pkcs11
- name: Ensure pam_pkcs11 is missing
ansible.builtin.package:
name: "{{ ipasmartcard_client_remove_pam_pkcs11_packages }}"
state: absent
# KINIT
- name: Set default principal if not given
ansible.builtin.set_fact:
ipaadmin_principal: admin
when: ipaadmin_principal is undefined
- name: Authenticate using kinit with password for "{{ ipaadmin_principal }}"
ansible.builtin.command: kinit "{{ ipaadmin_principal }}"
args:
stdin: "{{ ipaadmin_password }}"
when: ipaadmin_password is defined
- name: Authenticate using kinit with keytab for "{{ ipaadmin_principal }}"
ansible.builtin.command: kinit -kt "{{ ipaadmin_keytab }}" "{{ ipaadmin_principal }}"
when: ipaadmin_keytab is defined
# Enable and start smartcard daemon
- name: Enable and start smartcard daemon
ansible.builtin.service:
name: pcscd
enabled: true
state: started
# GET VARS FROM IPA
- name: Get VARS from IPA
ipasmartcard_client_get_vars:
register: ipasmartcard_client_vars
# Add pkcs11 module to systemwide db
- name: Add pkcs11 module to systemwide db
ansible.builtin.script: ipasmartcard_client_add_pkcs11_module_to_systemwide_db.sh
"{{ ipasmartcard_client_vars.NSS_DB_DIR }}"
# Ensure /etc/sssd/pki exists
- name: Prepare for authselect
when: ipasmartcard_client_vars.USE_AUTHSELECT
block:
- name: Ensure /etc/sssd/pki exists
ansible.builtin.file:
path: /etc/sssd/pki
state: directory
mode: 0711
- name: Ensure /etc/sssd/pki/sssd_auth_ca_db.pem is absent
ansible.builtin.file:
path: /etc/sssd/pki/sssd_auth_ca_db.pem
state: absent
# Upload smartcard CA certificates to systemwide db
- name: Upload smartcard CA certificates to systemwide db
ansible.builtin.script: ipasmartcard_client_add_ca_to_systemwide_db.sh
"{{ item }}"
"{{ ipasmartcard_client_vars.NSS_DB_DIR }}"
with_items: "{{ result_validate_ca_certs.ca_cert_files }}"
# Newer version of sssd use OpenSSL and read the CA certs
# from /etc/sssd/pki/sssd_auth_ca_db.pem
- name: Add CA certs to /etc/sssd/pki/sssd_auth_ca_db.pem
ansible.builtin.script: ipasmartcard_client_add_ca_to_sssd_auth_ca_db.sh
"{{ item }}"
/etc/sssd/pki/sssd_auth_ca_db.pem
with_items: "{{ result_validate_ca_certs.ca_cert_files }}"
when: ipasmartcard_client_vars.USE_AUTHSELECT
# Update ipa CA certificate store
- name: Update ipa CA certificate store
ansible.builtin.command: ipa-certupdate
# Run authselect or authconfig to configure smartcard auth
- name: Use authselect to enable Smart Card authentication
ansible.builtin.command: authselect enable-feature with-smartcard
when: ipasmartcard_client_vars.USE_AUTHSELECT
- name: Use authconfig to enable Smart Card authentication
ansible.builtin.command: authconfig --enablesssd --enablesssdauth --enablesmartcard --smartcardmodule=sssd --smartcardaction=1 --updateall
when: not ipasmartcard_client_vars.USE_AUTHSELECT
# Set pam_cert_auth=True in /etc/sssd/sssd.conf
- name: Store NSS OCSP upgrade state
ansible.builtin.command: "{{ ipasmartcard_client_vars.python_interpreter }}"
args:
stdin: |
from SSSDConfig import SSSDConfig
c = SSSDConfig()
c.import_config()
c.set("pam", "pam_cert_auth", "True")
c.write()
when: ipasmartcard_client_vars.USE_AUTHSELECT
# Restart sssd
- name: Restart sssd
ansible.builtin.service:
name: sssd
state: restarted
### ALWAYS ###
always:
- name: Destroy Kerberos tickets
ansible.builtin.command: kdestroy -A
ansible-freeipa-master/roles/ipasmartcard_client/vars/ 0000775 0000000 0000000 00000000000 14600563364 0023513 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_client/vars/default.yml 0000664 0000000 0000000 00000000220 14600563364 0025654 0 ustar 00root root 0000000 0000000 ---
ipasmartcard_client_remove_pam_pkcs11_packages: [ "pam_pkcs11" ]
ipasmartcard_client_packages: [ "opensc", "dconf", "krb5-pkinit-openssl" ]
ansible-freeipa-master/roles/ipasmartcard_server/ 0000775 0000000 0000000 00000000000 14600563364 0022570 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_server/README.md 0000664 0000000 0000000 00000010126 14600563364 0024047 0 ustar 00root root 0000000 0000000 ipasmartcard_server role
========================
Description
-----------
This role allows to configure an IPA server (master or replica) for Smart Card authentication.
**Note**: The ansible-freeipa smartcard server role requires a configured IPA server with ipa-ca.DOMAIN resolvable by the DNS server.
With external DNS ipa-ca.DOMAIN needs to be set.
Features
--------
* Server setup for Smart Card authentication
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.5 and up are supported by this role.
Supported Distributions
-----------------------
* RHEL/CentOS 7.6+
* CentOS Stream 8+
* Fedora 26+
Requirements
------------
**Controller**
* Ansible version: 2.13+
**Node**
* Supported FreeIPA version (see above)
* Supported distribution (needed for package installation only, see above)
* Deployed IPA server
Limitations
-----------
Only the enablement of smartcards is supported by the role, there is no disablement. The disablement of features in IPA in not supported.
Usage
=====
Example inventory file with ipa server and replicas:
```ini
[ipaserver]
ipaserver.example.com
[ipareplicas]
ipareplica1.example.com
ipareplica2.example.com
[ipacluster:children]
ipaserver
ipareplicas
[ipacluster:vars]
ipaadmin_password=SomeADMINpassword
ipasmartcard_server_ca_certs=/etc/ipa/ca.crt
```
Example playbook to setup smartcard for the IPA server using admin password and ipasmartcard_server_ca_certs from inventory file:
```yaml
---
- name: Playbook to setup smartcard for IPA server
hosts: ipaserver
become: true
roles:
- role: ipasmartcard_server
state: present
```
Example playbook to setup smartcard for the IPA servers in ipareplicas group using admin password and ipasmartcard_server_ca_certs from inventory file:
```yaml
---
- name: Playbook to setup smartcard for IPA replicas
hosts: ipareplicas
become: true
roles:
- role: ipasmartcard_server
state: present
```
Example playbook to setup smartcard for the IPA servers in ipaserver and ipareplicas group using admin password and ipasmartcard_server_ca_certs from inventory file:
```yaml
---
- name: Playbook to setup smartcard for IPA server and replicas
hosts: ipaserver, ipareplicas
become: true
roles:
- role: ipasmartcard_server
state: present
```
Playbooks
=========
The playbooks needed to setup smartcard for the IPA server and the replicas are part of the repository in the playbooks folder.
```
install-smartcard-server.yml
install-smartcard-servers.yml
install-smartcard-replicas.yml
```
Please remember to link or copy the playbooks to the base directory of ansible-freeipa if you want to use the roles within the source archive.
How to setup smartcard for server
---------------------------------
```bash
ansible-playbook -v -i inventory/hosts install-smartcard-server.yml
```
This will setup the server for smartcard use.
How to setup smartcard for replicas
-----------------------------------
```bash
ansible-playbook -v -i inventory/hosts install-smartcard-replicas.yml
```
This will setup the replicas for smartcard use.
How to setup smartcard for server and replicas
----------------------------------------------
```bash
ansible-playbook -v -i inventory/hosts install-smartcard-servers.yml
```
This will setup the replicas for smartcard use.
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The kerberos principal used for admin. Will be set to `admin` if not set. (string) | no
`ipaadmin_password` | The password for the IPA admin user. As an alternative an admin user keytab can be used instead with `ipaadmin_keytab`. (string) | yes
`ipaadmin_keytab` | The admin keytab as an alternative to `ipaadmin_password`. (string) | no
`ipaserver_hostname` | Fully qualified name of the server. By default `ansible_facts['fqdn']` will be used. (string) | no
`ipaserver_domain` | The primary DNS domain of an existing IPA deployment. By default the domain will be used from ipa server-find result. (string) | no
`ipasmartcard_server_ca_certs` | The CA certificates for smartcard use. (list of string) | yes
Authors
=======
Thomas Woerner
ansible-freeipa-master/roles/ipasmartcard_server/defaults/ 0000775 0000000 0000000 00000000000 14600563364 0024377 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_server/defaults/main.yml 0000664 0000000 0000000 00000000122 14600563364 0026041 0 ustar 00root root 0000000 0000000 ---
# defaults file for ipasmartcard_server role
ipaserver_install_packages: yes
ansible-freeipa-master/roles/ipasmartcard_server/files/ 0000775 0000000 0000000 00000000000 14600563364 0023672 5 ustar 00root root 0000000 0000000 ipasmartcard_server_add_ca_to_sssd_auth_ca_db.sh 0000664 0000000 0000000 00000001663 14600563364 0035357 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_server/files #!/bin/bash -eu
# Authors:
# Thomas Woerner
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
cert_file=$1
db=$2
if [ -z "${cert_file}" ] || [ -z "${db}" ]; then
echo "Usage: $0 "
exit 1
fi
cat "${cert_file}" >> "${db}"
ipasmartcard_server_add_ca_to_systemwide_db.sh 0000664 0000000 0000000 00000001763 14600563364 0035115 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_server/files #!/bin/bash -eu
# Authors:
# Thomas Woerner
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
cert_file=$1
db=$2
if [ -z "${cert_file}" ] || [ -z "${db}" ]; then
echo "Usage: $0 "
exit 1
fi
uuid=$(uuidgen)
certutil -d "${db}" -A -i "${cert_file}" -n "Smart Card CA ${uuid}" -t CT,C,C
ansible-freeipa-master/roles/ipasmartcard_server/files/ipasmartcard_server_enable_ocsp_directive.sh 0000664 0000000 0000000 00000002220 14600563364 0034652 0 ustar 00root root 0000000 0000000 #!/bin/bash -eu
# Authors:
# Thomas Woerner
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
directive=$1
conf_file=$2
if [ -z "${directive}" ] || [ -z "${conf_file}" ]; then
echo "Usage: $0 "
exit 1
fi
if grep -q "${directive} " "${conf_file}"
then
sed -i.ipabkp -r "s/^#*[[:space:]]*${directive}[[:space:]]+(on|off)$/${directive} on/" "${conf_file}"
else
sed -i.ipabkp "/<\/VirtualHost>/i ${directive} on" "${conf_file}"
fi
ipasmartcard_server_mark_httpd_cert_as_trusted.sh 0000664 0000000 0000000 00000002272 14600563364 0035701 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_server/files #!/bin/bash -eu
# Authors:
# Thomas Woerner
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
directive=$1
nss_conf=$2
nickname=$3
alias_dir=$4
if [ -z "${directive}" ] || [ -z "${nss_conf}" ] || [ -z "${nickname}" ] ||
[ -z "${alias_dir}" ]
then
echo "Usage: $0 "
exit 1
fi
http_cert_nick=$(grep "${nickname}" "${nss_conf}" | cut -f 2 -d ' ')
certutil -M -n "$http_cert_nick" -d "${alias_dir}" -f "${alias_dir}/pwdfile.txt" -t "Pu,u,u"
ansible-freeipa-master/roles/ipasmartcard_server/library/ 0000775 0000000 0000000 00000000000 14600563364 0024234 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_server/library/ipasmartcard_server_get_vars.py 0000664 0000000 0000000 00000012146 14600563364 0032544 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipasmartcard_server_get_vars
short_description:
Get variables from ipaplatform and ipaserver and python interpreter.
description:
Get variables from ipaplatform and ipaserver and python interpreter.
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
- name: Get VARS from IPA
ipasmartcard_server_get_vars:
register: ipasmartcard_server_vars
'''
RETURN = '''
NSS_OCSP_ENABLED:
description:
Empty string for newer systems using ssl.conf and not nss.conf for
HTTP instance where OCSP_ENABLED and OCSP_DIRECTIVE are defined in
ipaserver.install.httpinstance, else NSS_OCSP_ENABLED imported from
ipaserver.install.httpinstance.
returned: always
type: str
NSS_OCSP_DIRECTIVE:
description:
Empty string for newer systems using ssl.conf and not nss.conf for
HTTP instance where OCSP_ENABLED and OCSP_DIRECTIVE are defined in
ipaserver.install.httpinstance, else NSSOCSP.
returned: always
type: str
NSS_NICKNAME_DIRECTIVE:
description:
Empty string for newer systems using ssl.conf and not nss.conf for
HTTP instance where OCSP_ENABLED and OCSP_DIRECTIVE are defined in
ipaserver.install.httpinstance, else NSSNickname
returned: always
type: str
OCSP_ENABLED:
description:
OCSP_ENABLED imported from ipaserver.install.httpinstance, if import
succeeds, else ""
returned: always
type: str
OCSP_DIRECTIVE:
description:
OCSP_DIRECTIVE imported from ipaserver.install.httpinstance, if import
succeeds, else ""
returned: always
type: str
HTTPD_SSL_CONF:
description: paths.HTTPD_SSL_CONF from ipaplatform
returned: always
type: str
HTTPD_NSS_CONF:
description: paths.HTTPD_NSS_CONF from ipaplatform
returned: always
type: str
HTTPD_ALIAS_DIR:
description: paths.HTTPD_ALIAS_DIR from ipaplatform
returned: always
type: str
allow_httpd_ifp:
description:
True if sssd_enable_ifp can be imported from ipaclient.install.client,
else false.
returned: always
type: bool
NSS_DB_DIR:
description: paths.NSS_DB_DIR from ipaplatform
returned: always
type: str
USE_AUTHSELECT:
description: True if "AUTHSELECT" is defined in paths
returned: always
type: bool
python_interpreter:
description: Python interpreter from sys.executable
returned: always
type: str
'''
import sys
from ansible.module_utils.basic import AnsibleModule
try:
from ipaplatform.paths import paths
try:
from ipaserver.install.httpinstance import OCSP_ENABLED, OCSP_DIRECTIVE
NSS_OCSP_ENABLED = ""
NSS_OCSP_DIRECTIVE = ""
NSS_NICKNAME_DIRECTIVE = ""
except ImportError:
from ipaserver.install.httpinstance import NSS_OCSP_ENABLED
NSS_OCSP_DIRECTIVE = "NSSOCSP"
NSS_NICKNAME_DIRECTIVE = "NSSNickname"
OCSP_ENABLED = ""
OCSP_DIRECTIVE = ""
try:
from ipaclient.install.client import sssd_enable_ifp
except ImportError:
sssd_enable_ifp = None
except ImportError as _err:
MODULE_IMPORT_ERROR = str(_err)
paths = None
sssd_enable_ifp = None
else:
MODULE_IMPORT_ERROR = None
def main():
ansible_module = AnsibleModule(
argument_spec={},
supports_check_mode=False,
)
if MODULE_IMPORT_ERROR is not None:
ansible_module.fail_json(msg=MODULE_IMPORT_ERROR)
ansible_module.exit_json(changed=False,
NSS_OCSP_ENABLED=NSS_OCSP_ENABLED,
NSS_OCSP_DIRECTIVE=NSS_OCSP_DIRECTIVE,
NSS_NICKNAME_DIRECTIVE=NSS_NICKNAME_DIRECTIVE,
OCSP_ENABLED=OCSP_ENABLED,
OCSP_DIRECTIVE=OCSP_DIRECTIVE,
HTTPD_SSL_CONF=paths.HTTPD_SSL_CONF,
HTTPD_NSS_CONF=paths.HTTPD_NSS_CONF,
HTTPD_ALIAS_DIR=paths.HTTPD_ALIAS_DIR,
allow_httpd_ifp=sssd_enable_ifp is not None,
NSS_DB_DIR=paths.NSS_DB_DIR,
USE_AUTHSELECT=hasattr(paths, "AUTHSELECT"),
python_interpreter=sys.executable)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipasmartcard_server/library/ipasmartcard_server_validate_ca_certs.py 0000664 0000000 0000000 00000006113 14600563364 0034363 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2022 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.0',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = '''
---
module: ipasmartcard_server_validate_ca_certs
short_description: Validate CA certs
description: Validate CA certs
options:
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
type: list
elements: str
required: no
author:
- Thomas Woerner (@t-woerner)
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os.path
from ansible.module_utils.basic import AnsibleModule
try:
from ipalib import x509
except ImportError:
x509 = None
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
ca_cert_files=dict(required=False, type='list', elements='str',
default=[]),
),
supports_check_mode=False,
)
# get parameters #
ca_cert_files = ansible_module.params.get('ca_cert_files')
# import check #
if x509 is None:
ansible_module.fail_json(msg="Failed to import x509 from ipalib")
# validate ca certs #
if ca_cert_files is not None:
if not isinstance(ca_cert_files, list):
ansible_module.fail_json(
msg="Expected list, got %s" % repr(ca_cert_files))
# remove duplicates
ca_cert_files = list(dict.fromkeys(ca_cert_files))
# validate
for cert in ca_cert_files:
if not os.path.exists(cert):
ansible_module.fail_json(msg="'%s' does not exist" % cert)
if not os.path.isfile(cert):
ansible_module.fail_json(msg="'%s' is not a file" % cert)
if not os.path.isabs(cert):
ansible_module.fail_json(
msg="'%s' is not an absolute file path" % cert)
try:
x509.load_certificate_from_file(cert)
except Exception:
ansible_module.fail_json(
msg="'%s' is not a valid certificate file" % cert)
# exit #
ansible_module.exit_json(changed=False,
ca_cert_files=ca_cert_files)
if __name__ == '__main__':
main()
ansible-freeipa-master/roles/ipasmartcard_server/meta/ 0000775 0000000 0000000 00000000000 14600563364 0023516 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_server/meta/main.yml 0000664 0000000 0000000 00000000571 14600563364 0025170 0 ustar 00root root 0000000 0000000 ---
dependencies: []
galaxy_info:
author: Thomas Woerner
description: A role to setup IPA server(s) for Smart Card authentication
company: Red Hat, Inc
license: GPLv3
min_ansible_version: "2.13"
platforms:
- name: Fedora
versions:
- all
- name: EL
versions:
- "7"
- "8"
galaxy_tags:
- identity
- ipa
- freeipa
- smartcard
ansible-freeipa-master/roles/ipasmartcard_server/tasks/ 0000775 0000000 0000000 00000000000 14600563364 0023715 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_server/tasks/main.yml 0000664 0000000 0000000 00000021262 14600563364 0025367 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipasmartcard_server role
- name: Uninstall smartcard server
ansible.builtin.fail:
msg: "Uninstalling smartcard for IPA is not supported"
when: state|default('present') == 'absent'
- name: Import variables specific to distribution
ansible.builtin.include_vars: "{{ item }}"
with_first_found:
- "vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_version'] }}.yml"
- "vars/{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "vars/{{ ansible_facts['distribution'] }}.yml"
# os_family is used as a fallback for distros which are not currently
# supported, but are based on a supported distro family. For example,
# Oracle, Rocky, Alma and Alibaba linux, which are all "RedHat" based.
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_version'] }}.yml"
- "vars/{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "vars/{{ ansible_facts['os_family'] }}.yml"
# If neither distro nor family is supported, try a default configuration.
- "vars/default.yml"
- name: Server configuration
block:
# CA CERTS
# Fail on empty "ipasmartcard_server_ca_certs"
- name: Fail on empty "ipasmartcard_server_ca_certs"
ansible.builtin.fail:
msg: "No CA certs given in 'ipasmartcard_server_ca_certs'"
when: ipasmartcard_server_ca_certs is not defined or
ipasmartcard_server_ca_certs | length < 1
# Validate ipasmartcard_server_ca_certs
- name: Validate CA certs "{{ ipasmartcard_server_ca_certs }}"
ipasmartcard_server_validate_ca_certs:
ca_cert_files: "{{ ipasmartcard_server_ca_certs }}"
register: result_validate_ca_certs
# INSTALL bind-utils
- name: Ensure bind utilities packages are installed
ansible.builtin.package:
name: "{{ ipasmartcard_server_bindutils_packages }}"
state: present
when: ipaserver_install_packages | bool
# KINIT
- name: Set default principal if not given
ansible.builtin.set_fact:
ipaadmin_principal: admin
when: ipaadmin_principal is undefined
- name: Athenticate with kinit and password for "{{ ipaadmin_principal }}"
ansible.builtin.command: kinit "{{ ipaadmin_principal }}"
args:
stdin: "{{ ipaadmin_password }}"
when: ipaadmin_password is defined
- name: Authenticate with kinit and keytab for "{{ ipaadmin_principal }}"
ansible.builtin.command: kinit -kt "{{ ipaadmin_keytab }}" "{{ ipaadmin_principal }}"
when: ipaadmin_keytab is defined
# IS MASTER
- name: Check that this is an IPA master
ansible.builtin.command: ipa server-show --raw "{{ ipaserver_hostname | default(ansible_facts['fqdn']) }}"
register: result_ipa_server_show
- name: Fail if not an IPA server
ansible.builtin.fail:
msg: "Not an IPA server"
when: result_ipa_server_show.failed
- name: Get Domain from server-find server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ (result_ipa_server_show.stdout | regex_search('cn: (.+)', '\\1'))[0].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Get ipa-ca records
ansible.builtin.command: "dig +short ipa-ca.{{ ipaserver_domain }}"
register: result_get_ipaca_records
- name: Fail if ipa-ca records are not resolvable
ansible.builtin.fail:
msg: "ipa-ca records are not resolvable"
when: result_get_ipaca_records.failed or
result_get_ipaca_records.stdout | length == 0
# GET VARS FROM IPA
- name: Get VARS from IPA
ipasmartcard_server_get_vars:
register: ipasmartcard_server_vars
# ENABLE NSS OCSP
- name: Enable the OCSP directive in nss.conf
ansible.builtin.script: ipasmartcard_server_enable_ocsp_directive.sh
"{{ ipasmartcard_server_vars.NSS_OCSP_DIRECTIVE }}"
"{{ ipasmartcard_server_vars.HTTPD_NSS_CONF }}"
when: ipasmartcard_server_vars.NSS_OCSP_ENABLED | length > 0
# MARK NSS HTTPD CERT AS TRUSTED
- name: Mark HTTPD CERT as trusted
ansible.builtin.script: ipasmartcard_server_mark_httpd_cert_as_trusted.sh
"{{ ipasmartcard_server_vars.NSS_OCSP_DIRECTIVE }}"
"{{ ipasmartcard_server_vars.HTTPD_NSS_CONF }}"
"{{ ipasmartcard_server_vars.NSS_NICKNAME_DIRECTIVE }}"
"{{ ipasmartcard_server_vars.HTTPD_ALIAS_DIR }}"
when: ipasmartcard_server_vars.NSS_OCSP_ENABLED | length > 0
# ENABLE SSL OCSP
- name: Enable the OCSP directive in ssl.conf
ansible.builtin.script: ipasmartcard_server_enable_ocsp_directive.sh
"{{ ipasmartcard_server_vars.OCSP_DIRECTIVE }}"
"{{ ipasmartcard_server_vars.HTTPD_SSL_CONF }}"
when: ipasmartcard_server_vars.OCSP_ENABLED | length > 0
# Restart apache
- name: Restart apache
ansible.builtin.service:
name: httpd
state: restarted
# RECORD HTTPD OCSP STATUS
# Store the NSS OCSP upgrade state
- name: Store NSS OCSP upgrade state
ansible.builtin.command: "{{ ipasmartcard_server_vars.python_interpreter }}"
args:
stdin: |
from ipaserver.install import sysupgrade
sysupgrade.set_upgrade_state("httpd", "{{ ipasmartcard_server_vars.NSS_OCSP_DIRECTIVE }}", True)
when: ipasmartcard_server_vars.NSS_OCSP_ENABLED | length > 0
# Store the SSL OCSP upgrade state
- name: Store SSL OCSP upgrade state
ansible.builtin.command: "{{ ipasmartcard_server_vars.python_interpreter }}"
args:
stdin: |
from ipaserver.install import sysupgrade
sysupgrade.set_upgrade_state("httpd", "{{ ipasmartcard_server_vars.OCSP_DIRECTIVE }}", True)
when: ipasmartcard_server_vars.OCSP_ENABLED | length > 0
# check whether PKINIT is configured on the master
- name: Enable PKINIT
ansible.builtin.command: ipa-pkinit-manage enable
# Enable OK-AS-DELEGATE flag on the HTTP principal
# This enables smart card login to WebUI
- name: Enable OK-AS-DELEGATE flag on the HTTP principal
ipaservice:
name: "HTTP/{{ ipaserver_hostname | default(ansible_facts['fqdn']) }}"
ok_to_auth_as_delegate: yes
# HTTPD IFP
- name: Allow HTTPD ifp
when: ipasmartcard_server_vars.allow_httpd_ifp
block:
# Allow Apache to access SSSD IFP
- name: Allow Apache to access SSSD IFP
ansible.builtin.command: "{{ ipasmartcard_server_vars.python_interpreter }}"
args:
stdin: |
import SSSDConfig
from ipaclient.install.client import sssd_enable_ifp
from ipaplatform.paths import paths
c = SSSDConfig.SSSDConfig()
c.import_config()
sssd_enable_ifp(c, allow_httpd=True)
c.write(paths.SSSD_CONF)
when: ipasmartcard_server_vars.OCSP_ENABLED | length > 0
# Restart sssd
- name: Restart sssd
ansible.builtin.service:
name: sssd
state: restarted
# Ensure /etc/sssd/pki exists
- name: Prepare for authselect
when: ipasmartcard_server_vars.USE_AUTHSELECT
block:
- name: Ensure /etc/sssd/pki exists
ansible.builtin.file:
path: /etc/sssd/pki
state: directory
mode: 0711
- name: Ensure /etc/sssd/pki/sssd_auth_ca_db.pem is absent
ansible.builtin.file:
path: /etc/sssd/pki/sssd_auth_ca_db.pem
state: absent
# Upload smartcard CA certificates to systemwide db
- name: Upload smartcard CA certificates to systemwide db
ansible.builtin.script: ipasmartcard_server_add_ca_to_systemwide_db.sh
"{{ item }}"
"{{ ipasmartcard_server_vars.NSS_DB_DIR }}"
with_items: "{{ result_validate_ca_certs.ca_cert_files }}"
# Newer version of sssd use OpenSSL and read the CA certs
# from /etc/sssd/pki/sssd_auth_ca_db.pem
- name: Add CA certs to /etc/sssd/pki/sssd_auth_ca_db.pem
ansible.builtin.script: ipasmartcard_server_add_ca_to_sssd_auth_ca_db.sh
"{{ item }}"
/etc/sssd/pki/sssd_auth_ca_db.pem
with_items: "{{ result_validate_ca_certs.ca_cert_files }}"
when: ipasmartcard_server_vars.USE_AUTHSELECT
# Install smartcard signing CA certs
- name: Install smartcard signing CA certs
ansible.builtin.command: ipa-cacert-manage install "{{ item }}" -t CT,C,C
with_items: "{{ result_validate_ca_certs.ca_cert_files }}"
# Update ipa CA certificate store
- name: Update ipa CA certificate store
ansible.builtin.command: ipa-certupdate
# Restart krb5kdc
- name: Restart krb5kdc
ansible.builtin.service:
name: krb5kdc
state: restarted
### ALWAYS ###
always:
- name: Destroy Kereberos tickets
ansible.builtin.command: kdestroy -A
ansible-freeipa-master/roles/ipasmartcard_server/vars/ 0000775 0000000 0000000 00000000000 14600563364 0023543 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/roles/ipasmartcard_server/vars/default.yml 0000664 0000000 0000000 00000000075 14600563364 0025714 0 ustar 00root root 0000000 0000000 ---
ipasmartcard_server_bindutils_packages: [ "bind-utils" ]
ansible-freeipa-master/setup.cfg 0000664 0000000 0000000 00000004626 14600563364 0017235 0 ustar 00root root 0000000 0000000 [metadata]
name = ansible-freeipa
summary = Ansible roles for FreeIPA
description-file =
README.md
home-page = https://github.com/freeipa/ansible-freeipa
classifier =
Intended Audience :: Developers
Intended Audience :: System Administrators
Operating System :: POSIX :: Linux
[pbr]
warnerrors = True
[wheel]
universal = 1
[files]
data_files =
/usr/share/ansible/roles/ipaclient = roles/ipaclient/*
/usr/share/ansible/roles/ipaserver = roles/ipaserver/*
/usr/share/ansible/roles/ipareplica = roles/ipareplica/*
[flake8]
extend-ignore = E203, D1, D212, D203, D400, D401
exclude = .git,__pycache__,.tox,.venv,.cache,.ansible-freeipa-tests
per-file-ignores =
plugins/*:E402
roles/*:E402
[pydocstyle]
inherit = false
ignore = D1,D212,D203
[pylint.MASTER]
disable =
consider-using-f-string, # f-string is not supported on Python2
unspecified-encoding, # open() does not provide `encoding` in Python2
use-maxsplit-arg,
redundant-u-string-prefix,
c-extension-no-member,
missing-module-docstring,
missing-class-docstring,
missing-function-docstring,
wrong-import-order,
ungrouped-imports,
wrong-import-position,
protected-access,
no-name-in-module,
too-many-arguments,
too-many-statements,
too-many-lines,
raise-missing-from,
duplicate-code,
broad-except,
too-many-branches,
too-many-locals,
fixme,
use-dict-literal
[pylint.BASIC]
good-names =
ex, i, j, k, Run, _, e, x, dn, cn, ip, os, unicode, __metaclass__, ds,
dt, ca,
# These are utils tools, and not part of the released collection.
galaxyfy-playbook, galaxyfy-README, galaxyfy-module-EXAMPLES,
module_EXAMPLES
[pylint.IMPORTS]
ignored-modules =
ansible.errors, ansible.plugins.action,
ansible.module_utils, ansible.module_utils.ansible_freeipa_module,
dns,
gssapi,
ipalib, ipalib.config, ipalib.constants, ipalib.krb_utils, ipalib.errors,
ipapython.ipautil, ipapython.dn, ipapython.version, ipapython.dnsutil,
ipapython.ipa_log_manager, ipapython,
ipaplatform, ipaplatform.paths, ipaplatform.tasks, ipapython.admintool,
ipaserver.install.installutils, ipaserver.install.server.install,
ipaserver.install,
ipaclient.install.ipachangeconf, ipaclient.install.client,
ipaserver.dcerpc,
jinja2,
os,
SSSDConfig
[pylint.REFACTORING]
max-nested-blocks = 9
[pylint.FORMAT]
max-line-length = 80
ansible-freeipa-master/setup.py 0000664 0000000 0000000 00000000575 14600563364 0017125 0 ustar 00root root 0000000 0000000 import setuptools
# In python < 2.7.4, a lazy loading of package `pbr` will break
# setuptools if some other modules registered functions in `atexit`.
# solution from: http://bugs.python.org/issue15881#msg170215
try:
import multiprocessing # noqa # pylint:disable=unused-import
except ImportError:
pass
setuptools.setup(
setup_requires=['pbr>=2.0.0'],
pbr=True)
ansible-freeipa-master/tests/ 0000775 0000000 0000000 00000000000 14600563364 0016546 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/README.md 0000664 0000000 0000000 00000013735 14600563364 0020036 0 ustar 00root root 0000000 0000000 # Running the tests
## Before starting
In order to run ansible-freeipa tests you will need to install the dependencies listed in the file `requirements-tests.txt` in your local machine. We'll call this local machine `controller`.
You will also need to have a remote host with freeipa server installed and configured. We'll call this remote host `ipaserver`.
Some other requirements:
* The `controller` must be able to connect to `ipaserver` through ssh using keys.
* IPA admin password must be `SomeADMINpassword`.
* Directory Server admin password must be `SomeDMpassword`.
To provide broader test coverage, `ipaserver` should be configured with DNS and KRA support, and playbook tests are written based on this configuration. Without such support, some tests are expected to fail. Use a different configuration to evaluate those scenarios. See also [ipaserver role](../roles/ipaserver/README.md).
## Running the tests
To run the tests run:
```
IPA_SERVER_HOST= pytest
```
If you need to run using a different user you can use `ANSIBLE_REMOTE_USER`
environment variable. For example:
```
ANSIBLE_REMOTE_USER=root IPA_SERVER_HOST= pytest
```
If you want to use ssh with password, you must set `IPA_SSH_PASSWORD`
environment variable. For example:
```
IPA_SSH_PASSWORD= IPA_SERVER_HOST= pytest
```
To run a single test use the full path with the following format:
```
IPA_SERVER_HOST= pytest tests/test_playbook_runs.py::sudorule::test_sudorule
```
To select which tests to run based on search use the option `-k`. For example:
```
IPA_SERVER_HOST= pytest -k dnszone
```
To see the ansible output use the option `--capture=sys`. For example:
```
IPA_SERVER_HOST= pytest --capture=sys
```
To see why tests were skipped use `-rs`. For example:
```
IPA_SERVER_HOST= pytest -rs
```
For a complete list of options check `pytest --help`.
### Disabling and enabling playbook tests
Sometimes it is useful to enable or disable specific playbook tests. To only run a subset of modules or tests, use the variables IPA_ENABLED_MODULES and IPA ENABLED_TESTS, to define a comma-separated list of modules or tests to be enabled. Any test or module not in the list will not be executed. For example, to run only `sudorule` and `sudocmd` tests:
```
IPA_ENABLE_MODULES="sudorule,sudocmd" IPA_SERVER_HOST= pytest
```
If all but a few selected tests are to be executed, use the IPA_DISABLED_MODULES or IPA_DISABLED_TESTS. For example, to run all, but "test_service_certificate" test:
```
IPA_DISABLED_TESTS=test_service_certificate IPA_SERVER_HOST= pytest
```
If none of this variables are defined, all tests will be executed.
To configure the tests that will run for your pull request, add a TEMP commit, with the configuration defined in the file `tests/azure/templates/variables.yml`. Set the variables `ipa_enable_modules`, `ipa_enable_tests`, `ipa_disable_modules`, and `ipa_disable_tests`, in the same way as the equivalent environment variables.
### Types of tests
#### Playbook tests
The playbook tests will run our roles / modules using Ansible with various parameters. Most of these tests will be executed more than once, to verify idempotence. In general those tests don't verify the state of the machine after the playbook is executed.
To select only these tests use the option `-m "playbook"`
#### Python tests (pytests)
The pytests are tests that will execute small playbooks and then will verify the test results immediately after, using python code for that.
To select only these tests on a test execution use the option `-m "not playbook"`.
## Running tests in a docker container
It's also possible to run the tests in a container.
### Creating a container to run the tests
Before setting up a container you will need to install molecule framework:
```
pip install molecule-plugins[docker]
```
Now you can start a test container using the following command:
```
molecule create -s c8s
```
Note: Currently the containers available for running the tests are:
* fedora-latest
* centos-7
* c8s
* c9s
### Running the tests inside the container
To run the tests you will use pytest (works the same as for VMs).
```
RUN_TESTS_IN_DOCKER=1 IPA_SERVER_HOST=c8s pytest
```
### Cleaning up after tests
After running the tests you should probably destroy the test container using:
```
molecule destroy -s c8s
```
See [Running the tests](#running-the-tests) section for more information on available options.
## Running local tests with upstream CI images
To run tests locally using the same images used by upstream CI use `utils/run-tests.sh`.
```
utils/run-tests.sh tests/config/test_config.yml
```
To run all tests for a single plugin, use the `-s` option with plugin directory name. This will search, recursively for playbooks named with the pattern `test_*.yml`. To run all playbook tests for `ipauser`:
```
utils/run-tests.sh -s user
```
When executed, `utils/run-tests.sh` will create a container (either using `docker` or `podman`) using one of the testing ansible-freeipa images (https://quay.io/repository/ansible-freeipa/upstream-tests?tab=tags), run the selected tests against the container, and remove the container after tests are executed. If a test fails the container is not removed, so the failure can be investigated.
It is possible to keep the container after the execution, even if tests succeed, using the `-C` option:
```
utils/run-tests.sh -s config -C
```
By default the tests are executed against the latest version of the Fedora image (`fedora-latest`). The testing image can be selected with the `-i` option. Use `-l` to list the available image names.
```
utils/run-tests.sh -i c9s tests/host/test_host.yml
```
## Upcoming/desired improvements:
* A script to pre-config the complete test environment using virsh.
* A test matrix to run tests against different distros in parallel (probably using tox).
ansible-freeipa-master/tests/ansible.cfg 0000664 0000000 0000000 00000000537 14600563364 0020651 0 ustar 00root root 0000000 0000000 [defaults]
roles_path = ../roles:~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
library = ../plugins/modules:~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
module_utils = ../plugins/module_utils:~/.ansible/plugins/module_utils:/usr/share/ansible/plugins/module_utils
host_key_checking = false
inject_facts_as_vars = false
ansible-freeipa-master/tests/automember/ 0000775 0000000 0000000 00000000000 14600563364 0020706 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/automember/test_automember.yml 0000664 0000000 0000000 00000035456 14600563364 0024645 0 ustar 00root root 0000000 0000000 ---
- name: Test automember
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
# CLEANUP TEST ITEMS
- name: Ensure group testgroup is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
state: absent
- name: Ensure hostgroup testhostgroup is absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
state: absent
- name: Ensure group automember rule testgroup is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
state: absent
automember_type: group
- name: Ensure hostgroup automember rule testhostgroup is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
state: absent
automember_type: hostgroup
# CREATE TEST ITEMS
# TESTS
- name: Ensure testgroup group is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
- name: Ensure testhostgroup hostgroup is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
- name: Ensure testgroup group automember rule is present
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
description: testgroup automember rule.
automember_type: group
register: result
failed_when: not result.changed or result.failed
- name: Ensure testgroup group automember rule is present again
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
description: testgroup automember rule.
automember_type: group
register: result
failed_when: result.changed or result.failed
- name: Change testgroup group automember rule description
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
description: testgroup automember rule description.
automember_type: group
register: result
failed_when: not result.changed or result.failed
- name: Ensure testgroup group automember rule has conditions
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
inclusive:
- key: 'uid'
expression: 'uid'
- key: 'uidnumber'
expression: 'uidnumber'
exclusive:
- key: 'uid'
expression: 'uid'
register: result
failed_when: not result.changed or result.failed
- name: Ensure testgroup group automember rule has conditions again
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
inclusive:
- key: 'uid'
expression: 'uid'
- key: 'uidnumber'
expression: 'uidnumber'
exclusive:
- key: 'uid'
expression: 'uid'
register: result
failed_when: result.changed or result.failed
- name: Add testgroup group automember rule member condition
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
action: member
inclusive:
- key: 'manager'
expression: 'uid=mscott'
register: result
failed_when: not result.changed or result.failed
- name: Ensure testgroup group automember rule has conditions
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
inclusive:
- key: 'uid'
expression: 'uid'
- key: 'uidnumber'
expression: 'uidnumber'
- key: 'manager'
expression: 'uid=mscott'
exclusive:
- key: 'uid'
expression: 'uid'
register: result
failed_when: result.changed or result.failed
- name: Remove testgroup group automember rule member condition
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
action: member
state: absent
inclusive:
- key: 'manager'
expression: 'uid=mscott'
register: result
failed_when: not result.changed or result.failed
- name: Ensure testgroup group automember rule has conditions again
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
inclusive:
- key: 'uid'
expression: 'uid'
- key: 'uidnumber'
expression: 'uidnumber'
exclusive:
- key: 'uid'
expression: 'uid'
register: result
failed_when: result.changed or result.failed
- name: Ensure testgroup group automember conditions fails on invalid inclusive key
ipaautomember:
ipaadmin_principal: admin
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
inclusive:
- key: cns
expression: 'foo'
action: member
register: result
failed_when: result.changed or not result.failed or
"Invalid automember condition key 'cns'" not in result.msg
- name: Ensure testgroup group automember conditions fails on invalid exlusive key
ipaautomember:
ipaadmin_principal: admin
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
exclusive:
- key: cns
expression: 'foo'
action: member
register: result
failed_when: result.changed or not result.failed or
"Invalid automember condition key 'cns'" not in result.msg
- name: Ensure testhostgroup hostgroup automember rule is present
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
description: testhostgroup automember rule
automember_type: hostgroup
register: result
failed_when: not result.changed or result.failed
- name: Ensure testhostgroup hostgroup automember rule is present again
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
description: testhostgroup automember rule
automember_type: hostgroup
register: result
failed_when: result.changed or result.failed
- name: Change testhostgroup hostgroup automember rule description
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
description: testhostgroup test automember rule
automember_type: hostgroup
register: result
failed_when: not result.changed or result.failed
- name: Ensure testhostgroup hostgroup automember rule has conditions
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
automember_type: hostgroup
inclusive:
- key: 'description'
expression: 'description'
- key: 'description'
expression: 'description'
exclusive:
- key: 'cn'
expression: 'cn'
register: result
failed_when: not result.changed or result.failed
- name: Ensure testhostgroup hostgroup automember rule has conditions again
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
automember_type: hostgroup
inclusive:
- key: 'description'
expression: 'description'
- key: 'description'
expression: 'description'
exclusive:
- key: 'cn'
expression: 'cn'
register: result
failed_when: result.changed or result.failed
- name: Add testhostgroup hostgroup automember rule member condition
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
automember_type: hostgroup
action: member
inclusive:
- key: 'fqdn'
expression: '.*.domain.com'
register: result
failed_when: not result.changed or result.failed
- name: Ensure testhostgroup hostgroup automember rule has conditions
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
automember_type: hostgroup
inclusive:
- key: 'description'
expression: 'description'
- key: 'description'
expression: 'description'
- key: 'fqdn'
expression: '.*.domain.com'
exclusive:
- key: 'cn'
expression: 'cn'
register: result
failed_when: result.changed or result.failed
- name: Remove testhostgroup hostgroup automember rule member condition
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
automember_type: hostgroup
action: member
state: absent
inclusive:
- key: 'fqdn'
expression: '.*.domain.com'
register: result
failed_when: not result.changed or result.failed
- name: Ensure testhostgroup hostgroup automember rule has conditions
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
automember_type: hostgroup
inclusive:
- key: 'description'
expression: 'description'
- key: 'description'
expression: 'description'
exclusive:
- key: 'cn'
expression: 'cn'
register: result
failed_when: result.changed or result.failed
- name: Ensure testhostgroup hostgroup automember conditions fails on invalid inclusive key
ipaautomember:
ipaadmin_principal: admin
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
automember_type: hostgroup
inclusive:
- key: cns
expression: 'foo'
action: member
register: result
failed_when: result.changed or not result.failed or
"Invalid automember condition key 'cns'" not in result.msg
- name: Ensure testhostgroup hostgroup automember conditions fails on invalid exlusive key
ipaautomember:
ipaadmin_principal: admin
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
automember_type: hostgroup
exclusive:
- key: cns
expression: 'foo'
action: member
register: result
failed_when: result.changed or not result.failed or
"Invalid automember condition key 'cns'" not in result.msg
# Tests for issue https://bugzilla.redhat.com/show_bug.cgi?id=1976922
- name: Ensure group testgroup is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
state: absent
automember_type: group
register: result
failed_when: not result.changed or result.failed
- name: Ensure group testgroup is present
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
description: Automember rule.
automember_type: group
inclusive:
- key: cn
expression: "@1"
exclusive:
- key: cn
expression: s
register: result
failed_when: not result.changed or result.failed
- name: Ensure group testgroup is present with updated description
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
description: New automember rule.
automember_type: group
register: result
failed_when: not result.changed or result.failed
- name: Ensure group testgroup is present with updated description, again
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
description: New automember rule.
automember_type: group
register: result
failed_when: result.changed or result.failed
- name: Verify inclusive and exclusive rules have not changed
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
inclusive:
- key: cn
expression: "@1"
exclusive:
- key: cn
expression: s
register: result
failed_when: result.changed or result.failed
- name: Verify no other rules existed.
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
inclusive: []
exclusive: []
action: member
state: absent
register: result
failed_when: result.changed or result.failed
# End of ests for issue https://bugzilla.redhat.com/show_bug.cgi?id=1976922
# CLEANUP TEST ITEMS
- name: Ensure group testgroup is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
state: absent
- name: Ensure hostgroup testhostgroup is absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
state: absent
- name: Ensure group automember rule testgroup is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
automember_type: group
name: testgroup
state: absent
- name: Ensure hostgroup automember rule testhostgroup is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
automember_type: hostgroup
name: testhostgroup
state: absent
ansible-freeipa-master/tests/automember/test_automember_client_context.yml 0000664 0000000 0000000 00000002467 14600563364 0027743 0 ustar 00root root 0000000 0000000 ---
- name: Test automember
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
automember_type: group
state: rebuilt
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test automember using client context, in client host.
ansible.builtin.import_playbook: test_automember.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test automember using client context, in server host.
ansible.builtin.import_playbook: test_automember.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/automember/test_automember_default_group.yml 0000664 0000000 0000000 00000011755 14600563364 0027561 0 ustar 00root root 0000000 0000000 ---
- name: Test automember default groups
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
# SET FACTS
# CLEANUP TEST ITEMS
- name: Ensure group testgroup is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
state: absent
- name: Ensure hostgroup testhostgroup is absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
state: absent
- name: Ensure automember default group is unset
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
default_group: ""
automember_type: group
- name: Ensure automember default hostgroup is unset
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
default_group: ""
automember_type: hostgroup
# CREATE TEST ITEMS
- name: Ensure group testgroup is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure hostgroup testhostgroup is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
state: present
register: result
failed_when: not result.changed or result.failed
# TESTS
# GROUP TEST
- name: Ensure automember default group is set to testgroup
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
default_group: testgroup
automember_type: group
register: result
failed_when: not result.changed or result.failed
- name: Ensure automember default group is set to testgroup, again
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
default_group: testgroup
automember_type: group
register: result
failed_when: result.changed or result.failed
- name: Ensure automember default group is unset
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
default_group: ""
automember_type: group
register: result
failed_when: not result.changed or result.failed
- name: Ensure automember default group is unset, again
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
default_group: ""
automember_type: group
register: result
failed_when: result.changed or result.failed
# HOSTGROUP TEST
- name: Ensure automember default hostgroup is set to testhostgroup
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
default_group: testhostgroup
automember_type: hostgroup
register: result
failed_when: not result.changed or result.failed
- name: Ensure automember default hostgroup is set to testhostgroup, again
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
default_group: testhostgroup
automember_type: hostgroup
register: result
failed_when: result.changed or result.failed
- name: Ensure automember default hostgroup is unset
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
default_group: ""
automember_type: hostgroup
register: result
failed_when: not result.changed or result.failed
- name: Ensure automember default hostgroup is unset, again
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
default_group: ""
automember_type: hostgroup
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure group testgroup is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
state: absent
- name: Ensure hostgroup testhostgroup is absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
state: absent
- name: Ensure automember default group is unset
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
default_group: ""
automember_type: group
- name: Ensure automember default hostgroup is unset
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
default_group: ""
automember_type: hostgroup
ansible-freeipa-master/tests/automember/test_automember_orphans_removed.yml 0000664 0000000 0000000 00000016626 14600563364 0030116 0 ustar 00root root 0000000 0000000 ---
- name: Test automember orphans_removed
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
# SET FACTS
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] |
join('.') }}"
when: ipaserver_domain is not defined
# CLEANUP TEST ITEMS
- name: Ensure user testuser is absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
state: absent
- name: Ensure group testgroup is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
state: absent
- name: Ensure host testhost is absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'testhost.' + ipaserver_domain }}"
state: absent
- name: Ensure hostgroup testhostgroup is absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
state: absent
- name: Ensure automember group testgroup is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
state: absent
- name: Ensure automember hostgroup testhostgroup is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
automember_type: hostgroup
state: absent
# CREATE TEST ITEMS
- name: Ensure user testuser is present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
first: Test
last: User
register: result
failed_when: not result.changed or result.failed
- name: Ensure host testhost is present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'testhost.' + ipaserver_domain }}"
force: yes
reverse: no
register: result
failed_when: not result.changed or result.failed
- name: Ensure group testgroup is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure hostgroup testhostgroup is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
state: present
register: result
failed_when: not result.changed or result.failed
# TESTS
# GROUP TEST
- name: Ensure automember group testgroup exists
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
register: result
failed_when: not result.changed or result.failed
- name: Ensure automember group condition exits for users
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
action: member
inclusive:
- key: uid
expression: uid
register: result
failed_when: not result.changed or result.failed
- name: Ensure group testgroup is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure group orphans have been removed
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
automember_type: group
state: orphans_removed
register: result
failed_when: not result.changed or result.failed
- name: Ensure group orphans have been removed again
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
automember_type: group
state: orphans_removed
register: result
failed_when: result.changed or result.failed
# HOSTGROUP TEST
- name: Ensure automember hostgroup testhostgroup exists
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
automember_type: hostgroup
register: result
failed_when: not result.changed or result.failed
- name: Ensure automember hostgroup condition exits for hosts
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
automember_type: hostgroup
action: member
inclusive:
- key: fqdn
expression: "{{ '.*.' + ipaserver_domain }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure hostgroup testhostgroup is absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure hostgroup orphans have been removed
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
automember_type: hostgroup
state: orphans_removed
register: result
failed_when: not result.changed or result.failed
- name: Ensure hostgroup orphans have been removed again
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
automember_type: hostgroup
state: orphans_removed
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure user testuser is absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
state: absent
- name: Ensure group testgroup is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
state: absent
- name: Ensure host testhost is absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'testhost.' + ipaserver_domain }}"
state: absent
- name: Ensure hostgroup testhostgroup is absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
state: absent
- name: Ensure automember group testgroup is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup
automember_type: group
state: absent
- name: Ensure automember hostgroup testhostgroup is absent
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup
automember_type: hostgroup
state: absent
ansible-freeipa-master/tests/automember/test_automember_rebuilt.yml 0000664 0000000 0000000 00000011227 14600563364 0026361 0 ustar 00root root 0000000 0000000 ---
- name: Test automember rebuilt
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
# SET FACTS
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] |
join('.') }}"
when: ipaserver_domain is not defined
# CLEANUP TEST ITEMS
- name: Ensure user testuser is absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
state: absent
- name: Ensure host testhost is absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'testhost.' + ipaserver_domain }}"
state: absent
# CREATE TEST ITEMS
- name: Ensure user testuser is present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
first: Test
last: User
register: result
failed_when: not result.changed or result.failed
- name: Ensure host testhost is present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'testhost.' + ipaserver_domain }}"
force: yes
reverse: no
register: result
failed_when: not result.changed or result.failed
# TESTS
- name: Ensure group membership has been rebuilt
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
automember_type: group
state: rebuilt
register: result
failed_when: not result.changed or result.failed
- name: Ensure group membership has been rebuilt no_wait
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
automember_type: group
no_wait: yes
state: rebuilt
register: result
failed_when: not result.changed or result.failed
- name: Ensure group membership for given users has been rebuilt
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
users:
- testuser
state: rebuilt
register: result
failed_when: not result.changed or result.failed
- name: Ensure hostgroup membership for given hosts has been rebuilt
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
hosts:
- "{{ 'testhost.' + ipaserver_domain }}"
state: rebuilt
register: result
failed_when: not result.changed or result.failed
- name: Ensure group membership for given users has been rebuilt with type group
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
automember_type: group
users:
- testuser
state: rebuilt
register: result
failed_when: not result.changed or result.failed
- name: Ensure hostgroup membership for given hosts has been rebuilt with type hostgroup
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
automember_type: hostgroup
hosts:
- "{{ 'testhost.' + ipaserver_domain }}"
state: rebuilt
register: result
failed_when: not result.changed or result.failed
- name: Ensure group membership rebuild fails with hosts
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
automember_type: group
hosts:
- "{{ 'testhost.' + ipaserver_domain }}"
state: rebuilt
register: result
failed_when: not result.failed or
"hosts can not be set when type is 'group'" not in result.msg
- name: Ensure hostgroup membership rebuild fails with users
ipaautomember:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
automember_type: hostgroup
users:
- testuser
state: rebuilt
register: result
failed_when: not result.failed or
"users can not be set when type is 'hostgroup'" not in result.msg
# CLEANUP TEST ITEMS
- name: Ensure user testuser is absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
state: absent
- name: Ensure host testhost is absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'testhost.' + ipaserver_domain }}"
state: absent
ansible-freeipa-master/tests/automount/ 0000775 0000000 0000000 00000000000 14600563364 0020601 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/automount/test_automountkey.yml 0000664 0000000 0000000 00000010402 14600563364 0025124 0 ustar 00root root 0000000 0000000 ---
- name: Test automountmap
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
tasks:
- name: Ensure test location TestLocation is present
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestLocation
- name: Ensure test map TestMap is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
- name: Ensure key NewKeyName is absent
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: NewKeyName
state: absent
- name: Ensure key TestKey is absent
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: NewKeyName
state: absent
- name: Execute Automount Key tests
block:
### test the key creation, and modification
- name: Ensure key TestKey is present
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: TestKey
info: 192.168.122.1:/exports
state: present
register: result
failed_when: result.failed or not result.changed
- name: Ensure key TestKey is present again
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: TestKey
info: 192.168.122.1:/exports
state: present
register: result
failed_when: result.failed or result.changed
## modify the key
- name: Ensure key TestKey information has been updated
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: TestKey
info: 192.168.122.1:/nfsshare
state: present
register: result
failed_when: result.failed or not result.changed
- name: Ensure key TestKey information has been updated again
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: TestKey
info: 192.168.122.1:/nfsshare
state: present
register: result
failed_when: result.failed or result.changed
## modify the name
- name: Ensure key TestKey has been renamed to NewKeyName
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: TestKey
new_name: NewKeyName
state: renamed
register: result
failed_when: result.failed or not result.changed
- name: Ensure key TestKey is absent
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: TestKey
state: absent
register: result
failed_when: result.failed or result.changed
- name: Ensure key NewKeyName is present
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: NewKeyName
info: 192.168.122.1:/nfsshare
state: present
register: result
failed_when: result.failed or result.changed
- name: Ensure failure when state is renamed and newname is not set
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: TestKey
state: renamed
register: result
failed_when: not result.failed
### cleanup after the tests
always:
- name: Ensure key NewKeyName is absent
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: NewKeyName
state: absent
- name: Ensure key TestKey is absent
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: NewKeyName
state: absent
- name: Ensure map TestMap is absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
state: absent
- name: Ensure location TestLocation is absent
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestLocation
state: absent
ansible-freeipa-master/tests/automount/test_automountkey_client_context.yml 0000664 0000000 0000000 00000002544 14600563364 0030236 0 ustar 00root root 0000000 0000000 ---
- name: Test automountkey
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
location: NoLocation
map: NoMap
key: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test automountlocation using client context, in client host.
ansible.builtin.import_playbook: test_automountkey.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test automountlocation using client context, in server host.
ansible.builtin.import_playbook: test_automountkey.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/automount/test_automountlocation.yml 0000664 0000000 0000000 00000007224 14600563364 0026154 0 ustar 00root root 0000000 0000000 ---
- name: Test automountlocation
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
- name: Ensure automountlocation TestLocations are absent before testing
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- TestLocation_01
- TestLocation_02
state: absent
- name: Ensure empty automountlocation does nothing
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: []
state: present
register: result
failed_when: not result.failed or "At least one location must be provided" not in result.msg
- name: Ensure empty automountlocation does nothing on absent
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: []
state: absent
register: result
failed_when: not result.failed or "At least one location must be provided" not in result.msg
- name: Ensure automountlocation TestLocation is present
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestLocation_01
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure automountlocation TestLocation is present again
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestLocation_01
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure automountlocation TestLocation is absent
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestLocation_01
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure automountlocation TestLocation is absent again
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestLocation_01
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure a list of automountlocations are present
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- TestLocation_01
- TestLocation_02
state: present
register: result
failed_when: result.failed or not result.changed
- name: Ensure a list of automountlocations exist
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- TestLocation_01
- TestLocation_02
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure a list of automountlocations are absent
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- TestLocation_01
- TestLocation_02
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure multiple automountlocations are absent
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- TestLocation_01
- TestLocation_02
- TestLocation_03
- TestLocation_04
state: absent
register: result
failed_when: result.changed or result.failed
ansible-freeipa-master/tests/automount/test_automountlocation_client_context.yml 0000664 0000000 0000000 00000002515 14600563364 0031254 0 ustar 00root root 0000000 0000000 ---
- name: Test automountlocation
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test automountlocation using client context, in client host.
ansible.builtin.import_playbook: test_automountlocation.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test automountlocation using client context, in server host.
ansible.builtin.import_playbook: test_automountlocation.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/automount/test_automountmap.yml 0000664 0000000 0000000 00000011516 14600563364 0025120 0 ustar 00root root 0000000 0000000 ---
- name: Test automountmap
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
tasks:
# setup environment
- name: Ensure test maps are absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name:
- TestMap01
- TestMap02
location: TestLocation
state: absent
- name: Ensure location TestLocation is absent
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestLocation
state: absent
- name: Ensure map TestMap is absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
state: absent
- name: Ensure location TestLocation is present
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestLocation
state: present
# TESTS
- name: Execute Automount Map tests
block:
- name: Ensure map TestMap is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
desc: "this is a test map that should be deleted by the test"
register: result
failed_when: result.failed or not result.changed
- name: Ensure map TestMap is present again
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
register: result
failed_when: result.failed or result.changed
- name: Ensure map TestMap has a different description
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
desc: "this is a changed description that should be deleted by the test"
register: result
failed_when: result.failed or not result.changed
- name: Ensure map TestMap has a different description, again
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
desc: "this is a changed description that should be deleted by the test"
register: result
failed_when: result.failed or result.changed
- name: Ensure map TestMap has an empty description
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
desc: ""
register: result
failed_when: result.failed or not result.changed
- name: Ensure map TestMap has an empty description, again
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
desc: ""
register: result
failed_when: result.failed or result.changed
- name: Ensure map TestMap is removed
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure map TestMap has been removed
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
state: absent
register: result
failed_when: result.failed or result.changed
- name: Ensure map TestMap01 is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap01
location: TestLocation
desc: "this is a changed description that should be deleted by the test"
register: result
failed_when: result.failed or not result.changed
- name: Ensure map TestMap02 is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap02
location: TestLocation
desc: "this is a changed description that should be deleted by the test"
register: result
failed_when: result.failed or not result.changed
- name: Ensure TestMap01 and TestMap02 are both absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name:
- TestMap01
- TestMap02
location: TestLocation
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure TestMap01 and TestMap02 are both absent again
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name:
- TestMap01
- TestMap02
location: TestLocation
state: absent
register: result
failed_when: result.failed or result.changed
# CLEAN UP
always:
- name: Ensure test maps are absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name:
- TestMap01
- TestMap02
location: TestLocation
state: absent
- name: Ensure location TestLocation is absent
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestLocation
state: absent
ansible-freeipa-master/tests/automount/test_automountmap_client_context.yml 0000664 0000000 0000000 00000002507 14600563364 0030222 0 ustar 00root root 0000000 0000000 ---
- name: Test automountmap
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
location: default
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test automountmap using client context, in client host.
ansible.builtin.import_playbook: test_automountmap.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test automountmap using client context, in server host.
ansible.builtin.import_playbook: test_automountmap.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/automount/test_automountmap_indirect.yml 0000664 0000000 0000000 00000010072 14600563364 0026775 0 ustar 00root root 0000000 0000000 ---
- name: Test automountmap
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
tasks:
# setup environment
- name: Ensure test maps are absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name:
- DirectMap
- IndirectMap
- IndirectMapDefault
- IndirectMapDefaultAbsolute
state: absent
- name: Ensure test location is present
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestIndirect
- name: Ensure parent map is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name: DirectMap
# TESTS
- name: Mount point cannot start with '/' if parentmap is not 'auto.master'
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name: IndirectMap
parentmap: DirectMap
mount: '/absolute/path/will/fail'
register: result
failed_when: not result.failed or 'mount point is relative to parent map' not in result.msg
- name: Ensure indirect map is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name: IndirectMap
parentmap: DirectMap
mount: indirect
register: result
failed_when: result.failed or not result.changed
- name: Ensure indirect map is present, again
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name: IndirectMap
parentmap: DirectMap
mount: indirect
register: result
failed_when: result.failed or result.changed
- name: Ensure indirect map is absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name: IndirectMap
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure indirect map is absent, again
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name: IndirectMap
state: absent
register: result
failed_when: result.failed or result.changed
- name: Ensure indirect map is present, after being deleted
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name: IndirectMap
parentmap: DirectMap
mount: indirect
register: result
failed_when: result.failed or not result.changed
- name: Ensure indirect map is present, after being deleted, again
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name: IndirectMap
parentmap: DirectMap
mount: indirect
register: result
failed_when: result.failed or result.changed
- name: Ensure indirect map is present with default parent (auto.master)
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name: IndirectMapDefault
mount: indirect_with_default
register: result
failed_when: result.failed or not result.changed
- name: Ensure indirect map is present with default parent (auto.master), again
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name: IndirectMapDefault
mount: indirect_with_default
register: result
failed_when: result.failed or result.changed
- name: Absolute paths must workd with 'auto.master'
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name: IndirectMapDefaultAbsolute
mount: /valid/path/indirect_with_default
register: result
failed_when: result.failed or not result.changed
# Cleanup
- name: Ensure test maps are absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
location: TestIndirect
name:
- DirectMap
- IndirectMap
- IndirectMapDefault
- IndirectMapDefaultAbsolute
state: absent
- name: Ensure test location is absent
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestIndirect
state: absent
ansible-freeipa-master/tests/azure/ 0000775 0000000 0000000 00000000000 14600563364 0017674 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/azure/azure-pipelines.yml 0000664 0000000 0000000 00000003222 14600563364 0023532 0 ustar 00root root 0000000 0000000 ---
trigger:
- master
pool:
vmImage: 'ubuntu-20.04'
stages:
# Fedora
- stage: Fedora_Ansible_Latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core"
# Fedora
- stage: Fedora_Ansible_min_supported
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core <2.14"
# Fedora
- stage: Fedora_Latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.14,<2.15"
# Galaxy on Fedora
- stage: Galaxy_Fedora_Latest
dependsOn: []
jobs:
- template: templates/galaxy_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.14,<2.15"
# CentOS 9 Stream
- stage: CentOS_9_Stream
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: "-core >=2.14,<2.15"
# CentOS 8 Stream
- stage: CentOS_8_Stream
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: "-core >=2.14,<2.15"
# CentOS 7
- stage: CentOS_7
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: "-core >=2.14,<2.15"
ansible-freeipa-master/tests/azure/build-containers.yml 0000664 0000000 0000000 00000002347 14600563364 0023667 0 ustar 00root root 0000000 0000000 ---
schedules:
- cron: "0 0 * * 0"
displayName: Weekly Sunday midnight build
branches:
include:
- master
always: true
trigger: none
pool:
vmImage: 'ubuntu-20.04'
stages:
- stage: CentOS_7
dependsOn: []
jobs:
- template: templates/build_container.yml
parameters:
job_name_suffix: Centos7
container_name: centos-7
build_scenario_name: centos-7-build
- stage: CentOS_8_Stream
dependsOn: []
jobs:
- template: templates/build_container.yml
parameters:
job_name_suffix: C8S
container_name: c8s
build_scenario_name: c8s-build
- stage: CentOS_9_Stream
dependsOn: []
jobs:
- template: templates/build_container.yml
parameters:
job_name_suffix: C9S
container_name: c9s
build_scenario_name: c9s-build
- stage: Fedora_Latest
dependsOn: []
jobs:
- template: templates/build_container.yml
parameters:
job_name_suffix: FedoraLatest
container_name: fedora-latest
build_scenario_name: fedora-latest-build
- stage: Fedora_Rawhide
dependsOn: []
jobs:
- template: templates/build_container.yml
parameters:
job_name_suffix: FedoraRawhide
container_name: fedora-rawhide
build_scenario_name: fedora-rawhide-build
ansible-freeipa-master/tests/azure/nightly.yml 0000664 0000000 0000000 00000013035 14600563364 0022077 0 ustar 00root root 0000000 0000000 ---
schedules:
- cron: "0 19 * * *"
displayName: Nightly Builds
branches:
include:
- master
always: true
trigger: none
pool:
vmImage: 'ubuntu-20.04'
stages:
# Fedora
- stage: FedoraLatest_Ansible_Core_2_13
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.13,<2.14"
- stage: FedoraLatest_Ansible_Core_2_14
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.14,<2.15"
- stage: FedoraLatest_Ansible_Core_2_15
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.15,<2.16"
- stage: FedoraLatest_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: ""
# Galaxy on Fedora
- stage: Galaxy_FedoraLatest_Ansible_Core_2_13
dependsOn: []
jobs:
- template: templates/galaxy_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.13,<2.14"
- stage: Galaxy_FedoraLatest_Ansible_Core_2_14
dependsOn: []
jobs:
- template: templates/galaxy_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.14,<2.15"
- stage: Galaxy_FedoraLatest_Ansible_Core_2_15
dependsOn: []
jobs:
- template: templates/galaxy_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.15,<2.16"
- stage: Galaxy_FedoraLatest_Ansible_latest
dependsOn: []
jobs:
- template: templates/galaxy_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: ""
# Fedora Rawhide
- stage: FedoraRawhide_Ansible_Core_2_13
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-rawhide
ansible_version: "-core >=2.13,<2.14"
- stage: FedoraRawhide_Ansible_Core_2_14
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-rawhide
ansible_version: "-core >=2.14,<2.15"
- stage: FedoraRawhide_Ansible_Core_2_15
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-rawhide
ansible_version: "-core >=2.15,<2.16"
- stage: FedoraRawhide_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-rawhide
ansible_version: ""
# CentoOS 9 Stream
- stage: c9s_Ansible_Core_2_13
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: "-core >=2.13,<2.14"
- stage: c9s_Ansible_Core_2_14
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: "-core >=2.14,<2.15"
- stage: c9s_Ansible_Core_2_15
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: "-core >=2.15,<2.16"
- stage: c9s_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: ""
# CentOS 8 Stream
- stage: c8s_Ansible_Core_2_13
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: "-core >=2.13,<2.14"
- stage: c8s_Ansible_Core_2_14
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: "-core >=2.14,<2.15"
- stage: c8s_Ansible_Core_2_15
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: "-core >=2.15,<2.16"
- stage: c8s_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: ""
# CentOS 7
- stage: CentOS7_Ansible_Core_2_13
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: "-core >=2.13,<2.14"
- stage: CentOS7_Ansible_Core_2_14
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: "-core >=2.14,<2.15"
- stage: CentOS7_Ansible_Core_2_15
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: "-core >=2.15,<2.16"
- stage: CentOS7_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: ""
ansible-freeipa-master/tests/azure/pr-pipeline.yml 0000664 0000000 0000000 00000002646 14600563364 0022653 0 ustar 00root root 0000000 0000000 ---
trigger:
- master
pool:
vmImage: 'ubuntu-20.04'
stages:
# Fedora
- stage: Fedora_Latest
dependsOn: []
jobs:
- template: templates/fast_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.14,<2.15"
# Galaxy on Fedora
- stage: Galaxy_Fedora_Latest
dependsOn: []
jobs:
- template: templates/fast_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.14,<2.15"
# CentOS 9 Stream
- stage: CentOS_9_Stream
dependsOn: []
jobs:
- template: templates/fast_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: "-core >=2.14,<2.15"
# CentOS 8 Stream
- stage: CentOS_8_Stream
dependsOn: []
jobs:
- template: templates/fast_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: "-core >=2.14,<2.15"
# CentOS 7
- stage: CentOS_7
dependsOn: []
jobs:
- template: templates/fast_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: "-core >=2.14,<2.15"
# Rawhide
- stage: Fedora_Rawhide
dependsOn: []
jobs:
- template: templates/fast_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-rawhide
ansible_version: "-core >=2.14,<2.15"
ansible-freeipa-master/tests/azure/templates/ 0000775 0000000 0000000 00000000000 14600563364 0021672 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/azure/templates/build_container.yml 0000664 0000000 0000000 00000002607 14600563364 0025563 0 ustar 00root root 0000000 0000000 ---
parameters:
- name: job_name_suffix
type: string
- name: container_name
type: string
- name: build_scenario_name
type: string
- name: python_version
type: string
default: 3.x
jobs:
- job: BuildTestImage${{ parameters.job_name_suffix }}
displayName: Build ${{ parameters.container_name }} test container
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: python -m pip install --upgrade pip setuptools wheel ansible
retryCountOnTaskFailure: 5
displayName: Install tools
- script: pip install molecule-plugins[docker] "requests<2.29"
retryCountOnTaskFailure: 5
displayName: Install molecule
- script: molecule create -s ${{ parameters.build_scenario_name }}
retryCountOnTaskFailure: 5
displayName: Create test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
docker stop ${{ parameters.build_scenario_name }}
docker commit ${{ parameters.build_scenario_name }} quay.io/ansible-freeipa/upstream-tests:${{ parameters.container_name }}
docker login -u="$QUAY_ROBOT_USERNAME" -p="$QUAY_ROBOT_TOKEN" quay.io
docker push quay.io/ansible-freeipa/upstream-tests:${{ parameters.container_name }}
displayName: Save image and upload
env:
# Secrets needs to be mapped as env vars to work properly
QUAY_ROBOT_TOKEN: $(QUAY_ROBOT_TOKEN)
ansible-freeipa-master/tests/azure/templates/fast_tests.yml 0000664 0000000 0000000 00000001245 14600563364 0024576 0 ustar 00root root 0000000 0000000 ---
parameters:
- name: scenario
type: string
default: fedora-latest
- name: build_number
type: string
- name: ansible_version
type: string
default: ""
jobs:
- template: playbook_fast.yml
parameters:
group_number: 1
number_of_groups: 1
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
# - template: pytest_tests.yml
# parameters:
# build_number: ${{ parameters.build_number }}
# scenario: ${{ parameters.scenario }}
# ansible_version: ${{ parameters.ansible_version }}
# python_version: '< 3.12'
ansible-freeipa-master/tests/azure/templates/galaxy_pytest_script.yml 0000664 0000000 0000000 00000003260 14600563364 0026677 0 ustar 00root root 0000000 0000000 ---
parameters:
- name: build_number
type: string
- name: scenario
type: string
default: fedora-latest
- name: ansible_version
type: string
default: ""
- name: python_version
type: string
default: 3.x
jobs:
- job: Test_PyTests
displayName: Run pytests on ${{ parameters.scenario }}
timeoutInMinutes: 240
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install \
"molecule-plugins[docker]" \
"requests<2.29" \
"ansible${{ parameters.ansible_version }}"
retryCountOnTaskFailure: 5
displayName: Install molecule and Ansible
- script: ansible-galaxy collection install community.docker ansible.posix
retryCountOnTaskFailure: 5
displayName: Install Ansible collections
- script: pip install -r requirements-tests.txt
retryCountOnTaskFailure: 5
displayName: Install dependencies
- script: |
utils/build-galaxy-release.sh -i
molecule create -s ${{ parameters.scenario }}
retryCountOnTaskFailure: 5
displayName: Setup test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
cd ~/.ansible/collections/ansible_collections/freeipa/ansible_freeipa
pytest \
-m "not playbook" \
--verbose \
--color=yes \
--junit-xml=TEST-results-pytests.xml
displayName: Run tests
env:
IPA_SERVER_HOST: ${{ parameters.scenario }}
RUN_TESTS_IN_DOCKER: true
IPA_VERBOSITY: "-vvv"
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()
ansible-freeipa-master/tests/azure/templates/galaxy_script.yml 0000664 0000000 0000000 00000005046 14600563364 0025273 0 ustar 00root root 0000000 0000000 ---
parameters:
- name: group_number
type: number
default: 1
- name: number_of_groups
type: number
default: 1
- name: scenario
type: string
default: fedora-latest
- name: ansible_version
type: string
default: ""
- name: python_version
type: string
default: 3.x
- name: build_number
type: string
jobs:
- job: Test_Group${{ parameters.group_number }}
displayName: Run playbook tests ${{ parameters.scenario }} (${{ parameters.group_number }}/${{ parameters.number_of_groups }})
timeoutInMinutes: 240
variables:
- template: variables.yaml
- template: variables_${{ parameters.scenario }}.yaml
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install \
"molecule-plugins[docker]" \
"requests<2.29" \
"ansible${{ parameters.ansible_version }}"
retryCountOnTaskFailure: 5
displayName: Install molecule and Ansible
- script: ansible-galaxy collection install community.docker ansible.posix
retryCountOnTaskFailure: 5
displayName: Install Ansible collections
- script: pip install -r requirements-tests.txt
retryCountOnTaskFailure: 5
displayName: Install dependencies
- script: |
utils/build-galaxy-release.sh -i
molecule create -s ${{ parameters.scenario }}
retryCountOnTaskFailure: 5
displayName: Setup test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
python utils/check_test_configuration.py ${{ parameters.scenario }}
displayName: Check scenario test configuration
- script: |
cd ~/.ansible/collections/ansible_collections/freeipa/ansible_freeipa
pytest \
-m "playbook" \
--verbose \
--color=yes \
--splits=${{ parameters.number_of_groups }} \
--group=${{ parameters.group_number }} \
--randomly-seed=$(date "+%Y%m%d") \
--junit-xml=TEST-results-group-${{ parameters.group_number }}.xml
displayName: Run playbook tests
env:
IPA_SERVER_HOST: ${{ parameters.scenario }}
RUN_TESTS_IN_DOCKER: true
IPA_DISABLED_MODULES: ${{ variables.ipa_disabled_modules }}
IPA_DISABLED_TESTS: ${{ variables.ipa_disabled_tests }}
IPA_ENABLED_MODULES: ${{ variables.ipa_enabled_modules }}
IPA_ENABLED_TESTS: ${{ variables.ipa_enabled_tests }}
IPA_VERBOSITY: "-vvv"
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()
ansible-freeipa-master/tests/azure/templates/galaxy_tests.yml 0000664 0000000 0000000 00000002365 14600563364 0025132 0 ustar 00root root 0000000 0000000 ---
parameters:
- name: scenario
type: string
default: fedora-latest
- name: build_number
type: string
- name: ansible_version
type: string
default: ""
jobs:
- template: galaxy_script.yml
parameters:
group_number: 1
number_of_groups: 3
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
- template: galaxy_script.yml
parameters:
group_number: 2
number_of_groups: 3
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
- template: galaxy_script.yml
parameters:
group_number: 3
number_of_groups: 3
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
# Temporarily disable due to issues with ansible docker plugin.
#- template: galaxy_pytest_script.yml
# parameters:
# build_number: ${{ parameters.build_number }}
# scenario: ${{ parameters.scenario }}
# ansible_version: ${{ parameters.ansible_version }}
# python_version: '< 3.12'
ansible-freeipa-master/tests/azure/templates/group_tests.yml 0000664 0000000 0000000 00000002353 14600563364 0024776 0 ustar 00root root 0000000 0000000 ---
parameters:
- name: scenario
type: string
default: fedora-latest
- name: build_number
type: string
- name: ansible_version
type: string
default: ""
jobs:
- template: playbook_tests.yml
parameters:
group_number: 1
number_of_groups: 3
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
- template: playbook_tests.yml
parameters:
group_number: 2
number_of_groups: 3
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
- template: playbook_tests.yml
parameters:
group_number: 3
number_of_groups: 3
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
python_version: '< 3.12'
# Temporarily disabled due to ansible docker plugin issue.
#- template: pytest_tests.yml
# parameters:
# build_number: ${{ parameters.build_number }}
# scenario: ${{ parameters.scenario }}
# ansible_version: ${{ parameters.ansible_version }}
# python_version: '< 3.12'
ansible-freeipa-master/tests/azure/templates/playbook_fast.yml 0000664 0000000 0000000 00000005315 14600563364 0025256 0 ustar 00root root 0000000 0000000 ---
parameters:
- name: group_number
type: number
default: 1
- name: number_of_groups
type: number
default: 1
- name: scenario
type: string
default: fedora-latest
- name: ansible_version
type: string
default: ""
- name: python_version
type: string
default: 3.x
- name: build_number
type: string
jobs:
- job: Test_Group${{ parameters.group_number }}
displayName: Run playbook tests ${{ parameters.scenario }} (${{ parameters.group_number }}/${{ parameters.number_of_groups }})
timeoutInMinutes: 360
variables:
- template: variables.yaml
- template: variables_${{ parameters.scenario }}.yaml
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install \
"molecule-plugins[docker]" \
"requests<2.29" \
"ansible${{ parameters.ansible_version }}"
retryCountOnTaskFailure: 5
displayName: Install molecule and Ansible
- script: ansible-galaxy collection install community.docker ansible.posix
retryCountOnTaskFailure: 5
displayName: Install Ansible collections
- script: pip install -r requirements-tests.txt
retryCountOnTaskFailure: 5
displayName: Install dependencies
- script: |
rm -rf ~/ansible
mkdir -p ~/.ansible/roles ~/.ansible/library ~/.ansible/module_utils
cp -a roles/* ~/.ansible/roles
cp -a plugins/modules/* ~/.ansible/library
cp -a plugins/module_utils/* ~/.ansible/module_utils
molecule create -s ${{ parameters.scenario }}
retryCountOnTaskFailure: 5
displayName: Setup test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
. utils/set_test_modules
python utils/check_test_configuration.py ${{ parameters.scenario }}
displayName: Check scenario test configuration
- script: |
. utils/set_test_modules
if ! pytest \
-m "playbook" \
--verbose \
--color=yes \
--suppress-no-test-exit-code \
--splits=${{ parameters.number_of_groups }} \
--group=${{ parameters.group_number }} \
--randomly-seed=$(date "+%Y%m%d") \
--junit-xml=TEST-results-group-${{ parameters.group_number }}.xml
then
[ $? -eq 5 ] && true || false
fi
displayName: Run playbook tests
env:
IPA_SERVER_HOST: ${{ parameters.scenario }}
RUN_TESTS_IN_DOCKER: true
IPA_DISABLED_MODULES: ${{ variables.ipa_disabled_modules }}
IPA_DISABLED_TESTS: ${{ variables.ipa_disabled_tests }}
IPA_VERBOSITY: "-vvv"
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()
ansible-freeipa-master/tests/azure/templates/playbook_tests.yml 0000664 0000000 0000000 00000005245 14600563364 0025465 0 ustar 00root root 0000000 0000000 ---
parameters:
- name: group_number
type: number
default: 1
- name: number_of_groups
type: number
default: 1
- name: scenario
type: string
default: fedora-latest
- name: ansible_version
type: string
default: ""
- name: python_version
type: string
default: 3.x
- name: build_number
type: string
jobs:
- job: Test_Group${{ parameters.group_number }}
displayName: Run playbook tests ${{ parameters.scenario }} (${{ parameters.group_number }}/${{ parameters.number_of_groups }})
timeoutInMinutes: 240
variables:
- template: variables.yaml
- template: variables_${{ parameters.scenario }}.yaml
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install \
"molecule-plugins[docker]" \
"requests<2.29" \
"ansible${{ parameters.ansible_version }}"
retryCountOnTaskFailure: 5
displayName: Install molecule and Ansible
- script: ansible-galaxy collection install community.docker ansible.posix
retryCountOnTaskFailure: 5
displayName: Install Ansible collections
- script: pip install -r requirements-tests.txt
retryCountOnTaskFailure: 5
displayName: Install dependencies
- script: |
rm -rf ~/ansible
mkdir -p ~/.ansible/roles ~/.ansible/library ~/.ansible/module_utils
cp -a roles/* ~/.ansible/roles
cp -a plugins/modules/* ~/.ansible/library
cp -a plugins/module_utils/* ~/.ansible/module_utils
molecule create -s ${{ parameters.scenario }}
retryCountOnTaskFailure: 5
displayName: Setup test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
python utils/check_test_configuration.py ${{ parameters.scenario }}
displayName: Check scenario test configuration
- script: |
pytest \
-m "playbook" \
--verbose \
--color=yes \
--splits=${{ parameters.number_of_groups }} \
--group=${{ parameters.group_number }} \
--randomly-seed=$(date "+%Y%m%d") \
--junit-xml=TEST-results-group-${{ parameters.group_number }}.xml
displayName: Run playbook tests
env:
IPA_SERVER_HOST: ${{ parameters.scenario }}
RUN_TESTS_IN_DOCKER: true
IPA_DISABLED_MODULES: ${{ variables.ipa_disabled_modules }}
IPA_DISABLED_TESTS: ${{ variables.ipa_disabled_tests }}
IPA_ENABLED_MODULES: ${{ variables.ipa_enabled_modules }}
IPA_ENABLED_TESTS: ${{ variables.ipa_enabled_tests }}
IPA_VERBOSITY: "-vvv"
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()
ansible-freeipa-master/tests/azure/templates/pytest_tests.yml 0000664 0000000 0000000 00000004217 14600563364 0025173 0 ustar 00root root 0000000 0000000 ---
parameters:
- name: build_number
type: string
- name: scenario
type: string
default: fedora-latest
- name: ansible_version
type: string
default: ""
- name: python_version
type: string
default: 3.x
jobs:
- job: Test_PyTests
displayName: Run pytests on ${{ parameters.scenario }}
timeoutInMinutes: 240
variables:
- template: variables.yaml
- template: variables_${{ parameters.scenario }}.yaml
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install \
"molecule-plugins[docker]" \
"requests<2.29" \
"ansible${{ parameters.ansible_version }}"
retryCountOnTaskFailure: 5
displayName: Install molecule and Ansible
- script: ansible-galaxy collection install community.docker ansible.posix
retryCountOnTaskFailure: 5
displayName: Install Ansible collections
- script: pip install -r requirements-tests.txt
retryCountOnTaskFailure: 5
displayName: Install dependencies
- script: |
rm -rf ~/.ansible
mkdir -p ~/.ansible/roles ~/.ansible/library ~/.ansible/module_utils
cp -a roles/* ~/.ansible/roles
cp -a plugins/modules/* ~/.ansible/library
cp -a plugins/module_utils/* ~/.ansible/module_utils
molecule create -s ${{ parameters.scenario }}
retryCountOnTaskFailure: 5
displayName: Setup test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
pytest \
-m "not playbook" \
--verbose \
--color=yes \
--junit-xml=TEST-results-pytests.xml
displayName: Run tests
env:
IPA_SERVER_HOST: ${{ parameters.scenario }}
RUN_TESTS_IN_DOCKER: true
IPA_DISABLED_MODULES: ${{ variables.ipa_disabled_modules }}
IPA_DISABLED_TESTS: ${{ variables.ipa_disabled_tests }}
IPA_ENABLED_MODULES: ${{ variables.ipa_enabled_modules }}
IPA_ENABLED_TESTS: ${{ variables.ipa_enabled_tests }}
IPA_VERBOSITY: "-vvv"
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()
ansible-freeipa-master/tests/azure/templates/variables.yaml 0000664 0000000 0000000 00000000752 14600563364 0024532 0 ustar 00root root 0000000 0000000 #
# Variables must be defined as comma separated lists.
# For easier management of items to enable/disable,
# use one test/module on each line, followed by a comma.
#
# If no variable is to be set, add 'empty: true', as the
# 'variables' dict cannot be empty.
#
# Example:
#
# disabled_modules: >-
# dnsconfig,
# group,
# hostgroup
#
---
variables:
# empty: true
# ipa_enabled_modules: >-
# ipa_enabled_tests: >-
ipa_disabled_modules: >-
config
# ipa_disabled_tests: >-
ansible-freeipa-master/tests/azure/templates/variables_c8s.yaml 0000664 0000000 0000000 00000000736 14600563364 0025311 0 ustar 00root root 0000000 0000000 #
# Variables must be defined as comma separated lists.
# For easier management of items to enable/disable,
# use one test/module on each line, followed by a comma.
#
# Example:
#
# ipa_disabled_modules: >-
# dnsconfig,
# group,
# hostgroup
#
# If no variables are set, set "empty: true" as at least
# one item is needed in the set.
---
variables:
empty: true
# ipa_enabled_modules: >-
# ipa_enabled_tests: >-
# ipa_disabled_modules: >-
# ipa_disabled_tests: >-
ansible-freeipa-master/tests/azure/templates/variables_c9s.yaml 0000664 0000000 0000000 00000000736 14600563364 0025312 0 ustar 00root root 0000000 0000000 #
# Variables must be defined as comma separated lists.
# For easier management of items to enable/disable,
# use one test/module on each line, followed by a comma.
#
# Example:
#
# ipa_disabled_modules: >-
# dnsconfig,
# group,
# hostgroup
#
# If no variables are set, set "empty: true" as at least
# one item is needed in the set.
---
variables:
empty: true
# ipa_enabled_modules: >-
# ipa_enabled_tests: >-
# ipa_disabled_modules: >-
# ipa_disabled_tests: >-
ansible-freeipa-master/tests/azure/templates/variables_centos-7.yaml 0000664 0000000 0000000 00000000733 14600563364 0026250 0 ustar 00root root 0000000 0000000 #
# Variables must be defined as comma separated lists.
# For easier management of items to enable/disable,
# use one test/module on each line, followed by a comma.
#
# Example:
#
# ipa_disabled_modules: >-
# dnsconfig,
# group,
# hostgroup
#
# If no variables are set, set "empty: true" as at least
# one item is needed in the set.
---
variables:
# ipa_enabled_modules: >-
# ipa_enabled_tests: >-
# ipa_disabled_modules: >-
ipa_disabled_tests: test_config_sid
ansible-freeipa-master/tests/azure/templates/variables_fedora-latest.yaml 0000664 0000000 0000000 00000000740 14600563364 0027341 0 ustar 00root root 0000000 0000000 #
#
# Variables must be defined as comma separated lists.
# For easier management of items to enable/disable,
# use one test/module on each line, followed by a comma.
#
# Example:
#
# ipa_disabled_modules: >-
# dnsconfig,
# group,
# hostgroup
#
# If no variables are set, set "empty: true" as at least
# one item is needed in the set.
---
variables:
empty: true
# ipa_enabled_modules: >-
# ipa_enabled_tests: >-
# ipa_disabled_modules: >-
# ipa_disabled_tests: >-
ansible-freeipa-master/tests/azure/templates/variables_fedora-rawhide.yaml 0000664 0000000 0000000 00000000736 14600563364 0027475 0 ustar 00root root 0000000 0000000 #
# Variables must be defined as comma separated lists.
# For easier management of items to enable/disable,
# use one test/module on each line, followed by a comma.
#
# Example:
#
# ipa_disabled_modules: >-
# dnsconfig,
# group,
# hostgroup
#
# If no variables are set, set "empty: true" as at least
# one item is needed in the set.
---
variables:
empty: true
# ipa_enabled_modules: >-
# ipa_enabled_tests: >-
# ipa_disabled_modules: >-
# ipa_disabled_tests: >-
ansible-freeipa-master/tests/backup_role/ 0000775 0000000 0000000 00000000000 14600563364 0021034 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/backup_role/test_backup.yml 0000664 0000000 0000000 00000026372 14600563364 0024075 0 ustar 00root root 0000000 0000000 ---
- name: Test ansible-freeipa backup role
hosts: ipaserver
become: yes
gather_facts: yes
tasks:
- name: List all directories on server backup directory
ansible.builtin.find:
path: /var/lib/ipa/backup
file_type: directory
register: backup_dirs
- name: List all files on server backup directory
ansible.builtin.find:
path: /var/lib/ipa/backup
file_type: file
register: backup_files
- name: Remove all files and directories on server backup directory
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ backup_dirs.files + backup_files.files }}"
loop_control:
label: "{{ item.path }}"
- name: List all existing backups on controller
ansible.builtin.find:
path: "{{ lookup('env', 'PWD') }}"
pattern: "{{ ansible_facts.fqdn }}*"
file_type: directory
register: backups
delegate_to: localhost
become: no
- name: Remove all existing backups on controller
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ backups.files }}"
loop_control:
label: "{{ item.path }}"
delegate_to: localhost
become: no
# TESTS
# Test simple backup on server
- name: Remove all backup from server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: absent
ipabackup_name: all
- name: Backup ipaserver and leave data files on server
ansible.builtin.include_role:
name: ipabackup
vars:
state: present
- name: Verify backup on server.
ansible.builtin.find:
paths: /var/lib/ipa/backup/
recurse: no
file_type: directory
register: result
failed_when: not result.files
# Test backup and copy to controller, don't keep copy on server
- name: Remove all backup from server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: absent
ipabackup_name: all
- name: List all existing backups on controller
ansible.builtin.find:
path: "{{ lookup('env', 'PWD') }}"
pattern: "{{ ansible_facts.fqdn }}*"
file_type: directory
register: backups
delegate_to: localhost
become: no
- name: Remove all existing backups on controller
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ backups.files }}"
loop_control:
label: "{{ item.path }}"
delegate_to: localhost
become: no
- name: Backup ipaserver copying files to controller
ansible.builtin.include_role:
name: ipabackup
vars:
state: present
ipabackup_to_controller: yes
- name: Verify backup on server.
ansible.builtin.find:
paths: /var/lib/ipa/backup
recurse: no
file_type: directory
register: backups
failed_when: backups.files
- name: Verify backup on controller.
ansible.builtin.find:
path: "{{ lookup('env', 'PWD') }}"
pattern: "{{ ansible_facts.fqdn }}*"
file_type: directory
register: backups
failed_when: not backups.files
delegate_to: localhost
become: no
# Test backup and copy to controller, keep copy on server
- name: Remove all backup from server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: absent
ipabackup_name: all
- name: List all existing backups on controller
ansible.builtin.find:
path: "{{ lookup('env', 'PWD') }}"
pattern: "{{ ansible_facts.fqdn }}*"
file_type: directory
register: backups
delegate_to: localhost
become: no
- name: Remove all existing backups on controller
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ backups.files }}"
loop_control:
label: "{{ item.path }}"
delegate_to: localhost
become: no
- name: Backup ipaserver copying files to controller, keep copy on server
ansible.builtin.include_role:
name: ipabackup
vars:
state: present
ipabackup_to_controller: yes
ipabackup_keep_on_server: yes
- name: Verify backup on server.
ansible.builtin.find:
paths: /var/lib/ipa/backup
recurse: no
file_type: directory
register: result
failed_when: not result.files
- name: Verify backup on controller.
ansible.builtin.find:
path: "{{ lookup('env', 'PWD') }}"
pattern: "{{ ansible_facts.fqdn }}*"
file_type: directory
register: backups
failed_when: not backups.files
delegate_to: localhost
become: no
# Copy all backups from server
- name: List all existing backups on server
ansible.builtin.find:
path: /var/lib/ipa/backup
recurse: no
file_type: directory
register: server_backups
- name: List all existing backups on controller
ansible.builtin.find:
path: "{{ lookup('env', 'PWD') }}"
pattern: "{{ ansible_facts.fqdn }}*"
file_type: directory
register: backups
delegate_to: localhost
become: no
- name: Remove all existing backups on controller
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ backups.files }}"
loop_control:
label: "{{ item.path }}"
delegate_to: localhost
become: no
- name: Copy all backups from server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: copied
ipabackup_name: all
ipabackup_to_controller: yes
- name: Check all existing backups on controller
ansible.builtin.find:
path: "{{ lookup('env', 'PWD') }}"
pattern: "{{ ansible_facts.fqdn }}*"
file_type: directory
register: backups
failed_when: not backups.files
delegate_to: localhost
become: no
# Copy backup from controller to server
- name: Remove all backup from server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: absent
ipabackup_name: all
- name: List all existing backups on controller
ansible.builtin.find:
path: "{{ lookup('env', 'PWD') }}"
pattern: "{{ ansible_facts.fqdn }}*"
file_type: directory
register: backups
failed_when: not backups.files
delegate_to: localhost
become: no
- name: Copy backup from controller to server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: copied
ipabackup_name: "{{ ipa_backup_data.path | split('/') | last }}"
ipabackup_from_controller: yes
with_items: "{{ backups.files }}"
loop_control:
loop_var: ipa_backup_data
- name: Check all existing backups on server
ansible.builtin.find:
path: /var/lib/ipa/backup
file_type: directory
register: backups
failed_when: not backups.files
# Copy backup from server to controller
- name: List all existing backups on controller
ansible.builtin.find:
path: "{{ lookup('env', 'PWD') }}"
pattern: "{{ ansible_facts.fqdn }}*"
file_type: directory
register: backups
delegate_to: localhost
become: no
- name: Remove all existing backups on controller
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ backups.files }}"
loop_control:
label: "{{ item.path }}"
delegate_to: localhost
become: no
- name: List all existing backups on server
ansible.builtin.find:
path: /var/lib/ipa/backup
recurse: no
file_type: directory
register: server_backups
failed_when: not server_backups.files
- name: Copy backup from server to controller.
ansible.builtin.include_role:
name: ipabackup
vars:
state: copied
ipabackup_name: "{{ server_backup_data.path | split('/') | last }}"
ipabackup_to_controller: yes
loop: "{{ server_backups.files }}"
loop_control:
loop_var: server_backup_data
label: server_backup_data.path
- name: List all existing backups on controller
ansible.builtin.find:
path: "{{ lookup('env', 'PWD') }}"
pattern: "{{ ansible_facts.fqdn }}*"
file_type: directory
register: backups
failed_when: not backups.files
delegate_to: localhost
become: no
# Remove all backups from server
- name: List all existing backups on server
ansible.builtin.find:
path: /var/lib/ipa/backup
recurse: no
file_type: directory
register: backups
failed_when: not backups.files
- name: Remov all backup from server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: absent
ipabackup_name: all
- name: List all existing backups on server
ansible.builtin.find:
path: /var/lib/ipa/backup
recurse: no
file_type: directory
register: backups
failed_when: backups.files
# Remove all backups from server
- name: Create a backup on the server
ansible.builtin.include_role:
name: ipabackup
vars:
state: present
- name: Remove all backup from server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: absent
ipabackup_name: all
- name: List all existing backups on server
ansible.builtin.find:
path: /var/lib/ipa/backup
recurse: no
file_type: directory
register: backups
failed_when: backups.files
# Remove all backup from server
- name: Remove all backup from server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: absent
ipabackup_name: all
- name: Create a backup on the server
ansible.builtin.include_role:
name: ipabackup
vars:
state: present
- name: List all existing backups on server
ansible.builtin.find:
path: /var/lib/ipa/backup
recurse: no
file_type: directory
register: server_backups
failed_when: not server_backups.files
- name: Remove backup from server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: absent
ipabackup_name: "{{ server_backup_data.path | split('/') | last }}"
loop: "{{ server_backups.files }}"
loop_control:
loop_var: server_backup_data
label: server_backup_data.path
# Test issue #900
- name: Remove all backup from server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: absent
ipabackup_name: all
- name: Test issue 900 fix.
block:
- name: Invalid role configuration that should not produce a backup on the server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: present
ipabackup_name: this_must_fail
rescue:
- name: List all existing backups on server
ansible.builtin.find:
path: /var/lib/ipa/backup
recurse: no
file_type: directory
register: server_backups
failed_when: server_backups.files
# CLEANUP
- name: List all existing backups on controller
ansible.builtin.find:
path: "{{ lookup('env', 'PWD') }}"
pattern: "{{ ansible_facts.fqdn }}*"
file_type: directory
register: backups
delegate_to: localhost
become: no
- name: Remove all existing backups on controller
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ backups.files }}"
loop_control:
label: "{{ item.path }}"
delegate_to: localhost
become: no
- name: Remove all backup from server.
ansible.builtin.include_role:
name: ipabackup
vars:
state: absent
ipabackup_name: all
ansible-freeipa-master/tests/ca-less/ 0000775 0000000 0000000 00000000000 14600563364 0020075 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/ca-less/certificates/ 0000775 0000000 0000000 00000000000 14600563364 0022542 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/ca-less/certificates/extensions.conf 0000664 0000000 0000000 00000000324 14600563364 0025607 0 ustar 00root root 0000000 0000000 basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
authorityKeyIdentifier = keyid,issuer
subjectAltName = @alt_names
[alt_names]
DNS.1 = ${ENV::HOST_FQDN}
ansible-freeipa-master/tests/ca-less/certificates/pkinit-extensions.conf 0000664 0000000 0000000 00000001120 14600563364 0027076 0 ustar 00root root 0000000 0000000 basicConstraints = CA:FALSE
keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
extendedKeyUsage = 1.3.6.1.5.2.3.5
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
issuerAltName = issuer:copy
subjectAltName = otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name
[kdc_princ_name]
realm = EXP:0,GeneralString:${ENV::REALM_NAME}
principal_name = EXP:1,SEQUENCE:kdc_principal_seq
[kdc_principal_seq]
name_type = EXP:0,INTEGER:1
name_string = EXP:1,SEQUENCE:kdc_principals
[kdc_principals]
princ1 = GeneralString:krbtgt
princ2 = GeneralString:${ENV::REALM_NAME}
ansible-freeipa-master/tests/ca-less/clean_up_certificates.yml 0000664 0000000 0000000 00000000376 14600563364 0025141 0 ustar 00root root 0000000 0000000 ---
- name: Clean up certificates
hosts: localhost
gather_facts: false
tasks:
- name: Run generate-certificates.sh
ansible.builtin.command: >
/bin/bash
generate-certificates.sh cleanup
args:
chdir: "{{ playbook_dir }}"
ansible-freeipa-master/tests/ca-less/generate-certificates.sh 0000775 0000000 0000000 00000011411 14600563364 0024667 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
CERTIFICATES="certificates"
ROOT_CA_DIR="${CERTIFICATES}/root-ca"
DIRSRV_CERTS_DIR="${CERTIFICATES}/dirsrv"
HTTPD_CERTS_DIR="${CERTIFICATES}/httpd"
PKINIT_CERTS_DIR="${CERTIFICATES}/pkinit"
EXTENSIONS_CONF="${CERTIFICATES}/extensions.conf"
PKINIT_EXTENSIONS_CONF="${CERTIFICATES}/pkinit-extensions.conf"
PKCS12_PASSWORD="SomePKCS12password"
# create_ca \
# $domain_name
function create_ca {
domain_name=$1
if [ -z "${domain_name}" ]; then
echo "ERROR: domain is not set"
echo
echo "usage: $0 ca "
exit 0;
fi
realm=${domain_name^^}
export REALM_NAME=${realm}
# Create certificates folder structure
mkdir -p "${ROOT_CA_DIR}"
# Create root CA
if [ ! -f "${ROOT_CA_DIR}/private.key" ]; then
# create aes encrypted private key
openssl genrsa -out "${ROOT_CA_DIR}/private.key" 4096
# create certificate, 1826 days = 5 years
openssl req -x509 -new -nodes -sha256 -days 1826 \
-subj "/C=US/ST=Test/L=Testing/O=Default/CN=Test Root CA" \
-key "${ROOT_CA_DIR}/private.key" \
-out "${ROOT_CA_DIR}/cert.pem"
fi
}
# create_host_pkcs12_certificate \
# $cert_name $certs_dir $root_ca_cert $extensions_file
function create_host_pkcs12_certificate {
cert_name=$1
certs_dir=$2
root_ca_cert=$3
extensions_file=$4
# Create CSR and private key
openssl req -new -nodes -newkey rsa:4096 \
-subj "/C=US/ST=Test/L=Testing/O=Default/CN=${cert_name}" \
-keyout "${certs_dir}/private.key" \
-out "${certs_dir}/request.csr"
# Sign CSR to create PEM certificate
openssl x509 -req -days 1460 -sha256 -CAcreateserial \
-CAkey "${ROOT_CA_DIR}/private.key" \
-CA "${root_ca_cert}" \
-in "${certs_dir}/request.csr" \
-out "${certs_dir}/cert.pem" \
-extfile "${extensions_file}"
# Convert certificate to PKCS12 format
openssl pkcs12 -export \
-name "${cert_name}" \
-certfile "${root_ca_cert}" \
-passout "pass:${PKCS12_PASSWORD}" \
-inkey "${certs_dir}/private.key" \
-in "${certs_dir}/cert.pem" \
-out "${certs_dir}/cert.p12"
}
# create_ipa_pkcs12_certificates \
# $host_fqdn $domain_name
function create_host_certificates {
host_fqdn=$1
if [ -z "${host_fqdn}" ]; then
echo "ERROR: host-fqdn is not set"
echo
echo "usage: $0 create []"
exit 0;
fi
domain_name=$2
[ -z "${domain_name}" ] && domain_name=${host_fqdn#*.*}
if [ -z "${domain_name}" ]; then
echo "ERROR: domain is not set and can not be created from host fqdn"
echo
echo "usage: $0 create []"
exit 0;
fi
realm=${domain_name^^}
export HOST_FQDN=${host_fqdn}
export REALM_NAME=${realm}
if [ ! -f "${ROOT_CA_DIR}/private.key" ]; then
create_ca "${domain_name}"
fi
# Create certificates folder structure
mkdir -p "${DIRSRV_CERTS_DIR}/${host_fqdn}"
mkdir -p "${HTTPD_CERTS_DIR}/${host_fqdn}"
mkdir -p "${PKINIT_CERTS_DIR}/${host_fqdn}"
# Create a certificate for the Directory Server
if [ ! -f "${DIRSRV_CERTS_DIR}/${host_fqdn}/cert.pem" ]; then
create_host_pkcs12_certificate \
"dirsrv-cert" \
"${DIRSRV_CERTS_DIR}/${host_fqdn}" \
"${ROOT_CA_DIR}/cert.pem" \
"${EXTENSIONS_CONF}"
fi
# Create a certificate for the Apache server
if [ ! -f "${HTTPD_CERTS_DIR}/${host_fqdn}/cert.pem" ]; then
create_host_pkcs12_certificate \
"httpd-cert" \
"${HTTPD_CERTS_DIR}/${host_fqdn}" \
"${ROOT_CA_DIR}/cert.pem" \
"${EXTENSIONS_CONF}"
fi
# Create a certificate for the KDC PKINIT
if [ ! -f "${PKINIT_CERTS_DIR}/${host_fqdn}/cert.pem" ]; then
create_host_pkcs12_certificate \
"pkinit-cert" \
"${PKINIT_CERTS_DIR}/${host_fqdn}" \
"${ROOT_CA_DIR}/cert.pem" \
"${PKINIT_EXTENSIONS_CONF}"
fi
}
# delete_host_certificates \
# $host_fqdn
function delete_host_certificates {
host_fqdn=$1
if [ -z "${host_fqdn}" ]; then
echo "ERROR: host-fqdn is not set"
echo
echo "usage: $0 delete "
exit 0;
fi
rm -rf certificates/*/"${host_fqdn}"/
}
# cleanup \
# $host_fqdn
function cleanup {
rm -rf certificates/*/
}
# Entrypoint
case "$1" in
ca)
create_ca "$2"
;;
create)
create_host_certificates "$2" "$3"
;;
delete)
delete_host_certificates "$2"
;;
cleanup)
cleanup
;;
*)
echo $"Usage: $0 {create|delete|ca|cleanup}"
;;
esac
ansible-freeipa-master/tests/ca-less/install_replica_without_ca.yml 0000664 0000000 0000000 00000004331 14600563364 0026214 0 ustar 00root root 0000000 0000000 ---
- name: Generate certificates
hosts: localhost
gather_facts: false
tasks:
- name: Run generate-certificates.sh
ansible.builtin.command: >
/bin/bash
generate-certificates.sh create
"{{ groups.ipareplicas[0] }}"
"{{ ipareplica_domain | default(groups.ipareplicas[0].split('.')[1:] | join('.')) }}"
args:
chdir: "{{ playbook_dir }}"
- name: Test ipareplicas installation without CA
hosts: ipareplicas
become: true
vars:
# Root CA certificate
ipareplica_ca_cert_files:
- /root/ca-less-test/ca.crt
# Directory server certificates
ipareplica_dirsrv_cert_name: dirsrv-cert
ipareplica_dirsrv_cert_files:
- /root/ca-less-test/dirsrv.p12
ipareplica_dirsrv_pin: SomePKCS12password
# Apache certificates
ipareplica_http_cert_name: httpd-cert
ipareplica_http_cert_files:
- /root/ca-less-test/httpd.p12
ipareplica_http_pin: SomePKCS12password
# PKINIT configuration
ipareplica_no_pkinit: no
ipareplica_pkinit_cert_name: pkinit-cert
ipareplica_pkinit_cert_files:
- /root/ca-less-test/pkinit.p12
ipareplica_pkinit_pin: SomePKCS12password
pre_tasks:
- name: Remove "/root/ca-less-test"
ansible.builtin.file:
path: "/root/ca-less-test"
state: absent
- name: Generate "/root/ca-less-test"
ansible.builtin.file:
path: "/root/ca-less-test"
state: directory
mode: 0775
- name: Copy CA certificate
ansible.builtin.copy:
src: "{{ playbook_dir }}/certificates/root-ca/cert.pem"
dest: "/root/ca-less-test/ca.crt"
owner: root
group: root
mode: "0644"
- name: Copy p12 certificates
ansible.builtin.copy:
src: "{{ playbook_dir }}/certificates/{{ item }}/{{ groups.ipareplicas[0] }}/cert.p12"
dest: "/root/ca-less-test/{{ item }}.p12"
owner: root
group: root
mode: "0644"
with_items:
- dirsrv
- httpd
- pkinit
roles:
- role: ipareplica
state: present
post_tasks:
- name: Fix KDC certificate permissions
ansible.builtin.file:
path: /var/kerberos/krb5kdc/kdc.crt
owner: root
group: root
mode: '0644'
ansible-freeipa-master/tests/ca-less/install_server_without_ca.yml 0000664 0000000 0000000 00000004002 14600563364 0026076 0 ustar 00root root 0000000 0000000 ---
- name: Generate certificates
hosts: localhost
gather_facts: false
tasks:
- name: Run generate-certificates.sh
ansible.builtin.command: >
/bin/bash
generate-certificates.sh create
"{{ groups.ipaserver[0] }}"
"{{ ipaserver_domain | default(groups.ipaserver[0].split('.')[1:] | join('.')) }}"
args:
chdir: "{{ playbook_dir }}"
- name: Test ipaserver installation without CA
hosts: ipaserver
become: true
vars:
# Root CA certificate
ipaserver_ca_cert_files:
- /root/ca-less-test/ca.crt
# Directory server certificates
ipaserver_dirsrv_cert_name: dirsrv-cert
ipaserver_dirsrv_cert_files:
- /root/ca-less-test/dirsrv.p12
ipaserver_dirsrv_pin: SomePKCS12password
# Apache certificates
ipaserver_http_cert_name: httpd-cert
ipaserver_http_cert_files:
- /root/ca-less-test/httpd.p12
ipaserver_http_pin: SomePKCS12password
# PKINIT configuration
ipaserver_no_pkinit: no
ipaserver_pkinit_cert_name: pkinit-cert
ipaserver_pkinit_cert_files:
- /root/ca-less-test/pkinit.p12
ipaserver_pkinit_pin: SomePKCS12password
pre_tasks:
- name: Remove "/root/ca-less-test"
ansible.builtin.file:
path: "/root/ca-less-test"
state: absent
- name: Generate "/root/ca-less-test"
ansible.builtin.file:
path: "/root/ca-less-test"
state: directory
mode: 0775
- name: Copy CA certificate
ansible.builtin.copy:
src: "{{ playbook_dir }}/certificates/root-ca/cert.pem"
dest: "/root/ca-less-test/ca.crt"
owner: root
group: root
mode: "0644"
- name: Copy p12 certificates
ansible.builtin.copy:
src: "{{ playbook_dir }}/certificates/{{ item }}/{{ groups.ipaserver[0] }}/cert.p12"
dest: "/root/ca-less-test/{{ item }}.p12"
owner: root
group: root
mode: "0644"
with_items:
- dirsrv
- httpd
- pkinit
roles:
- role: ipaserver
state: present
ansible-freeipa-master/tests/ca-less/inventory 0000664 0000000 0000000 00000000537 14600563364 0022062 0 ustar 00root root 0000000 0000000 [ipaserver]
ipaserver.test.local
[ipaserver:vars]
ipaserver_domain=test.local
ipaserver_realm=TEST.LOCAL
ipaadmin_password=SomeADMINpassword
ipadm_password=SomeDMpassword
[ipareplicas]
ipareplica.test.local
[ipareplicas:vars]
ipareplica_domain=test.local
ipareplica_realm=TEST.LOCAL
ipaadmin_password=SomeADMINpassword
ipadm_password=SomeDMpassword ansible-freeipa-master/tests/cert/ 0000775 0000000 0000000 00000000000 14600563364 0017503 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/cert/test_cert_client_context.yml 0000664 0000000 0000000 00000004113 14600563364 0025323 0 ustar 00root root 0000000 0000000 ---
- name: Test cert
hosts: ipaclients, ipaserver
become: false
gather_facts: false
module_defaults:
ipacert:
ipaadmin_password: SomeADMINpassword
ipaapi_contetx: "{{ ipa_context | default(omit) }}"
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipacert:
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test host certs using client context, in client host.
ansible.builtin.import_playbook: test_cert_host.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test service certs using client context, in client host.
ansible.builtin.import_playbook: test_cert_service.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test user certs using client context, in client host.
ansible.builtin.import_playbook: test_cert_user.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test host certs using client context, in server host.
ansible.builtin.import_playbook: test_cert_host.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
- name: Test service certs using client context, in server host.
ansible.builtin.import_playbook: test_cert_service.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
- name: Test user certs using client context, in server host.
ansible.builtin.import_playbook: test_cert_user.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
ansible-freeipa-master/tests/cert/test_cert_host.yml 0000664 0000000 0000000 00000014454 14600563364 0023267 0 ustar 00root root 0000000 0000000 ---
- name: Test host certificate requests
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: false
gather_facts: false
module_defaults:
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipacert:
ipaadmin_password: SomeADMINpassword
# ipacert only supports client context
ipaapi_context: "client"
tasks:
# SETUP
- name: Ensure test files do not exist
ansible.builtin.file:
path: "{{ item }}"
state: absent
with_items:
- "/root/retrieved.pem"
- "/root/cert_1.pem"
- "/root/host.csr"
# Ensure test items exist
- name: Ensure domain name is set
ansible.builtin.set_fact:
ipa_domain: ipa.test
when: ipa_domain is not defined
- name: Ensure test host exists
ipahost:
name: "certhost.{{ ipa_domain }}"
state: present
force: true
- name: Create CSR
ansible.builtin.shell:
cmd: "openssl req -newkey rsa:1024 -keyout /dev/null -nodes -subj /CN=certhost.{{ ipa_domain }}"
register: host_req
- name: Create CSR file
ansible.builtin.copy:
dest: "/root/host.csr"
content: "{{ host_req.stdout }}"
mode: 0644
# TESTS
- name: Request certificate for host
ipacert:
csr: '{{ host_req.stdout }}'
principal: "host/certhost.{{ ipa_domain }}"
state: requested
register: host_cert
failed_when: not host_cert.changed or host_cert.failed
- name: Display data from the requested certificate.
ansible.builtin.debug:
var: host_cert
- name: Retrieve certificate for host
ipacert:
serial_number: "{{ host_cert.certificate.serial_number }}"
state: retrieved
register: retrieved
failed_when: retrieved.certificate.serial_number != host_cert.certificate.serial_number
- name: Display data from the retrieved certificate.
ansible.builtin.debug:
var: retrieved
- name: Place certificate on hold
ipacert:
serial_number: '{{ host_cert.certificate.serial_number }}'
state: held
register: result
failed_when: not result.changed or result.failed
- name: Place certificate on hold, again
ipacert:
serial_number: '{{ host_cert.certificate.serial_number }}'
state: held
register: result
failed_when: result.changed or result.failed
- name: Release hold on certificate
ipacert:
serial_number: '{{ host_cert.certificate.serial_number }}'
state: released
register: result
failed_when: not result.changed or result.failed
- name: Release hold on certificate, again
ipacert:
serial_number: '{{ host_cert.certificate.serial_number }}'
state: released
register: result
failed_when: result.changed or result.failed
- name: Revoke certificate
ipacert:
serial_number: '{{ host_cert.certificate.serial_number }}'
state: revoked
reason: keyCompromise
register: result
failed_when: not result.changed or result.failed
- name: Revoke certificate, again
ipacert:
serial_number: '{{ host_cert.certificate.serial_number }}'
state: revoked
reason: keyCompromise
register: result
failed_when: result.changed or result.failed
- name: Try to revoke inexistent certificate
ipacert:
serial_number: 0x123456789
reason: 9
state: revoked
register: result
failed_when: not (result.failed and ("Request failed with status 404" in result.msg or "Certificate serial number 0x123456789 not found" in result.msg))
- name: Try to release revoked certificate
ipacert:
serial_number: '{{ host_cert.certificate.serial_number }}'
state: released
register: result
failed_when: not result.failed or "Cannot release hold on certificate revoked with reason" not in result.msg
- name: Request certificate for host and save to file
ipacert:
csr: '{{ host_req.stdout }}'
principal: "host/certhost.{{ ipa_domain }}"
certificate_out: "/root/cert_1.pem"
state: requested
register: result
failed_when: not result.changed or result.failed or result.certificate
- name: Check requested certificate file
ansible.builtin.file:
path: "/root/cert_1.pem"
check_mode: true
register: result
failed_when: result.changed or result.failed
- name: Retrieve certificate for host to a file
ipacert:
serial_number: "{{ host_cert.certificate.serial_number }}"
certificate_out: "/root/retrieved.pem"
state: retrieved
register: result
failed_when: result.changed or result.failed or result.certificate
- name: Check retrieved certificate file
ansible.builtin.file:
path: "/root/retrieved.pem"
check_mode: true
register: result
failed_when: result.changed or result.failed
- name: Request with invalid CSR.
ipacert:
csr: |
-----BEGIN CERTIFICATE REQUEST-----
BNxXqLcHylNEyg8SH0u63bWyxtgoDBfdZwdGAhYuJ+g4ev79J5eYoB0CAwEAAaAr
MCkGCSqGSIb3DQEJDjEcMBowGAYHKoZIzlYIAQQNDAtoZWxsbyB3b3JsZDANBgkq
hkiG9w0BAQsFAAOBgQADCi5BHDv1mrBFDWqYytFpQ1mrvr/mdax3AYXxNL2UEV8j
AqZAFTEnJXL/u1eVQtI1yotqxakyUBN4XZBP2CBgJRO93Mtry8cgvU1sPdU8Mavx
5gSnlP74Hio2ziscWWydlxpYxFx0gkKvu+0nyIpz954SVYwQ2wwk5FRqZnxI5w==
-----END CERTIFICATE REQUEST-----
principal: "host/certhost.{{ ipa_domain }}"
state: requested
register: result
failed_when: not (result.failed and "Failure decoding Certificate Signing Request" in result.msg)
- name: Request certificate using a file
ipacert:
csr_file: "/root/host.csr"
principal: "host/certhost.{{ ipa_domain }}"
state: requested
register: result
failed_when: not result.changed or result.failed
- name: Request certificate using an invalid profile
ipacert:
csr_file: "/root/host.csr"
principal: "host/certhost.{{ ipa_domain }}"
profile: invalid_profile
state: requested
register: result
failed_when: not (result.failed and "Request failed with status 400" in result.msg)
# CLEANUP TEST ITEMS
- name: Removet test host
ipahost:
name: "certhost.{{ ipa_domain }}"
state: absent
- name: Ensure test files do not exist
ansible.builtin.file:
path: "{{ item }}"
state: absent
with_items:
- "/root/retrieved.pem"
- "/root/cert_1.pem"
- "/root/host.csr"
ansible-freeipa-master/tests/cert/test_cert_service.yml 0000664 0000000 0000000 00000015673 14600563364 0023756 0 ustar 00root root 0000000 0000000 ---
- name: Test service certificate requests
hosts: "{{ ipa_test_host | default('ipaserver') }}"
# Change "become" or "gather_facts" to "yes",
# if you test playbook requires any.
become: false
gather_facts: false
module_defaults:
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipacert:
ipaadmin_password: SomeADMINpassword
# ipacert only supports client context
ipaapi_context: "client"
tasks:
# SETUP
- name: Ensure test files do not exist
ansible.builtin.file:
path: "{{ item }}"
state: absent
with_items:
- "/root/retrieved.pem"
- "/root/cert_1.pem"
- "/root/service.csr"
# Ensure test items exist
- name: Ensure domain name is set
ansible.builtin.set_fact:
ipa_domain: ipa.test
when: ipa_domain is not defined
- name: Ensure test host exist
ipahost:
name: "certservice.{{ ipa_domain }}"
force: true
state: present
- name: Ensure service exist
ipaservice:
name: "HTTP/certservice.{{ ipa_domain }}"
force: true
state: present
- name: Create signing request for certificate
ansible.builtin.shell:
cmd: "openssl req -newkey rsa:1024 -keyout /dev/null -nodes -subj /CN=certservice.{{ ipa_domain }}"
register: service_req
- name: Create CSR file
ansible.builtin.copy:
dest: "/root/service.csr"
content: "{{ service_req.stdout }}"
mode: '0644'
# TESTS
- name: Request certificate for service
ipacert:
csr: '{{ service_req.stdout }}'
principal: "HTTP/certservice.{{ ipa_domain }}"
add_principal: true
state: requested
register: service_cert
failed_when: not service_cert.changed or service_cert.failed
- name: Display data from the requested certificate.
ansible.builtin.debug:
var: service_cert
- name: Retrieve certificate for service
ipacert:
serial_number: "{{ service_cert.certificate.serial_number }}"
state: retrieved
register: retrieved
failed_when: retrieved.certificate.serial_number != service_cert.certificate.serial_number
- name: Display data from the retrieved certificate.
ansible.builtin.debug:
var: retrieved
- name: Place certificate on hold
ipacert:
serial_number: '{{ service_cert.certificate.serial_number }}'
state: held
register: result
failed_when: not result.changed or result.failed
- name: Place certificate on hold, again
ipacert:
serial_number: '{{ service_cert.certificate.serial_number }}'
state: held
register: result
failed_when: result.changed or result.failed
- name: Release hold on certificate
ipacert:
serial_number: '{{ service_cert.certificate.serial_number }}'
state: released
register: result
failed_when: not result.changed or result.failed
- name: Release hold on certificate, again
ipacert:
serial_number: '{{ service_cert.certificate.serial_number }}'
state: released
register: result
failed_when: result.changed or result.failed
- name: Revoke certificate
ipacert:
serial_number: '{{ service_cert.certificate.serial_number }}'
state: revoked
reason: keyCompromise
register: result
failed_when: not result.changed or result.failed
- name: Revoke certificate, again
ipacert:
serial_number: '{{ service_cert.certificate.serial_number }}'
state: revoked
reason: keyCompromise
register: result
failed_when: result.changed or result.failed
- name: Try to revoke inexistent certificate
ipacert:
serial_number: 0x123456789
reason: 9
state: revoked
register: result
failed_when: not (result.failed and ("Request failed with status 404" in result.msg or "Certificate serial number 0x123456789 not found" in result.msg))
- name: Try to release revoked certificate
ipacert:
serial_number: '{{ service_cert.certificate.serial_number }}'
state: released
register: result
failed_when: not result.failed or "Cannot release hold on certificate revoked with reason" not in result.msg
- name: Request certificate for service and save to file
ipacert:
csr: '{{ service_req.stdout }}'
principal: "HTTP/certservice.{{ ipa_domain }}"
add_principal: true
certificate_out: "/root/cert_1.pem"
state: requested
register: result
failed_when: not result.changed or result.failed or result.certificate
- name: Check requested certificate file
ansible.builtin.file:
path: "/root/cert_1.pem"
check_mode: true
register: result
failed_when: result.changed or result.failed
- name: Retrieve certificate for service to a file
ipacert:
serial_number: "{{ service_cert.certificate.serial_number }}"
certificate_out: "/root/retrieved.pem"
state: retrieved
register: result
failed_when: result.changed or result.failed or result.certificate
- name: Check retrieved certificate file
ansible.builtin.file:
path: "/root/retrieved.pem"
check_mode: true
register: result
failed_when: result.changed or result.failed
- name: Request with invalid CSR.
ipacert:
csr: |
-----BEGIN CERTIFICATE REQUEST-----
BNxXqLcHylNEyg8SH0u63bWyxtgoDBfdZwdGAhYuJ+g4ev79J5eYoB0CAwEAAaAr
MCkGCSqGSIb3DQEJDjEcMBowGAYHKoZIzlYIAQQNDAtoZWxsbyB3b3JsZDANBgkq
hkiG9w0BAQsFAAOBgQADCi5BHDv1mrBFDWqYytFpQ1mrvr/mdax3AYXxNL2UEV8j
AqZAFTEnJXL/u1eVQtI1yotqxakyUBN4XZBP2CBgJRO93Mtry8cgvU1sPdU8Mavx
5gSnlP74Hio2ziscWWydlxpYxFx0gkKvu+0nyIpz954SVYwQ2wwk5FRqZnxI5w==
-----END CERTIFICATE REQUEST-----
principal: "HTTP/certservice.{{ ipa_domain }}"
state: requested
register: result
failed_when: not (result.failed and "Failure decoding Certificate Signing Request" in result.msg)
- name: Request certificate using a file
ipacert:
csr_file: "/root/service.csr"
principal: "HTTP/certservice.{{ ipa_domain }}"
state: requested
register: result
failed_when: not result.changed or result.failed
- name: Request certificate using an invalid profile
ipacert:
csr_file: "/root/service.csr"
principal: "HTTP/certservice.{{ ipa_domain }}"
profile: invalid_profile
state: requested
register: result
failed_when: not (result.failed and "Request failed with status 400" in result.msg)
# CLEANUP TEST ITEMS
- name: Remove test service
ipaservice:
name: "HTTP/certservice.{{ ipa_domain }}"
state: absent
continue: true
- name: Remove test host
ipahost:
name: certservice.example.com
state: absent
- name: Ensure test files do not exist
ansible.builtin.file:
path: "{{ item }}"
state: absent
with_items:
- "/root/retrieved.pem"
- "/root/cert_1.pem"
- "/root/service.csr"
ansible-freeipa-master/tests/cert/test_cert_user.yml 0000664 0000000 0000000 00000014405 14600563364 0023264 0 ustar 00root root 0000000 0000000 ---
- name: Test user certificate requests
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: false
gather_facts: false
module_defaults:
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipacert:
ipaadmin_password: SomeADMINpassword
# ipacert only supports client context
ipaapi_context: "client"
tasks:
# Ensure test files do not exist
- name: Check retrieved certificate file
ansible.builtin.file:
path: "{{ item }}"
state: absent
with_items:
- "/root/retrieved.pem"
- "/root/cert_1.pem"
- "/root/user.csr"
# Ensure test items exist.
- name: Ensure test user exists
ipauser:
name: certuser
first: certificate
last: user
- name: Crete CSR
ansible.builtin.shell:
cmd:
'openssl req -newkey rsa:1024 -keyout /dev/null -nodes -subj /CN=certuser -reqexts IECUserRoles
-config <(cat /etc/pki/tls/openssl.cnf; printf "[IECUserRoles]\n1.2.840.10070.8.1=ASN1:UTF8String:hello world")'
executable: /bin/bash
register: user_req
- name: Create CSR file
ansible.builtin.copy:
dest: "/root/user.csr"
content: "{{ user_req.stdout }}"
mode: 0644
# TESTS
- name: Request certificate for user
ipacert:
csr: '{{ user_req.stdout }}'
principal: certuser
profile: IECUserRoles
state: requested
register: user_cert
failed_when: not user_cert.changed or user_cert.failed
- name: Display data from the requested certificate.
ansible.builtin.debug:
var: user_cert
- name: Retrieve certificate for user
ipacert:
serial_number: "{{ user_cert.certificate.serial_number }}"
state: retrieved
register: retrieved
failed_when: retrieved.certificate.serial_number != user_cert.certificate.serial_number
- name: Display data from the retrieved certificate.
ansible.builtin.debug:
var: retrieved
- name: Place certificate on hold
ipacert:
serial_number: '{{ user_cert.certificate.serial_number }}'
state: held
register: result
failed_when: not result.changed or result.failed
- name: Place certificate on hold, again
ipacert:
serial_number: '{{ user_cert.certificate.serial_number }}'
state: held
register: result
failed_when: result.changed or result.failed
- name: Release hold on certificate
ipacert:
serial_number: '{{ user_cert.certificate.serial_number }}'
state: released
register: result
failed_when: not result.changed or result.failed
- name: Release hold on certificate, again
ipacert:
serial_number: '{{ user_cert.certificate.serial_number }}'
state: released
register: result
failed_when: result.changed or result.failed
- name: Revoke certificate
ipacert:
serial_number: '{{ user_cert.certificate.serial_number }}'
state: revoked
reason: keyCompromise
register: result
failed_when: not result.changed or result.failed
- name: Revoke certificate, again
ipacert:
serial_number: '{{ user_cert.certificate.serial_number }}'
state: revoked
reason: keyCompromise
register: result
failed_when: result.changed or result.failed
- name: Try to revoke inexistent certificate
ipacert:
serial_number: 0x123456789
reason: 9
state: revoked
register: result
failed_when: not (result.failed and ("Request failed with status 404" in result.msg or "Certificate serial number 0x123456789 not found" in result.msg))
- name: Try to release revoked certificate
ipacert:
serial_number: '{{ user_cert.certificate.serial_number }}'
state: released
register: result
failed_when: not result.failed or "Cannot release hold on certificate revoked with reason" not in result.msg
- name: Request certificate for user and save to file
ipacert:
csr: '{{ user_req.stdout }}'
principal: certuser
profile: IECUserRoles
certificate_out: "/root/cert_1.pem"
state: requested
register: result
failed_when: not result.changed or result.failed or result.certificate
- name: Check requested certificate file
ansible.builtin.file:
path: "/root/cert_1.pem"
check_mode: true
register: result
failed_when: result.changed or result.failed
- name: Retrieve certificate for user to a file
ipacert:
serial_number: "{{ user_cert.certificate.serial_number }}"
certificate_out: "/root/retrieved.pem"
state: retrieved
register: result
failed_when: result.changed or result.failed or result.certificate
- name: Check retrieved certificate file
ansible.builtin.file:
path: "/root/retrieved.pem"
check_mode: true
register: result
failed_when: result.changed or result.failed
- name: Request with invalid CSR.
ipacert:
csr: |
-----BEGIN CERTIFICATE REQUEST-----
BNxXqLcHylNEyg8SH0u63bWyxtgoDBfdZwdGAhYuJ+g4ev79J5eYoB0CAwEAAaAr
MCkGCSqGSIb3DQEJDjEcMBowGAYHKoZIzlYIAQQNDAtoZWxsbyB3b3JsZDANBgkq
hkiG9w0BAQsFAAOBgQADCi5BHDv1mrBFDWqYytFpQ1mrvr/mdax3AYXxNL2UEV8j
AqZAFTEnJXL/u1eVQtI1yotqxakyUBN4XZBP2CBgJRO93Mtry8cgvU1sPdU8Mavx
5gSnlP74Hio2ziscWWydlxpYxFx0gkKvu+0nyIpz954SVYwQ2wwk5FRqZnxI5w==
-----END CERTIFICATE REQUEST-----
principal: certuser
state: requested
register: result
failed_when: not (result.failed and "Failure decoding Certificate Signing Request" in result.msg)
- name: Request certificate using a file
ipacert:
csr_file: "/root/user.csr"
principal: certuser
state: requested
register: result
failed_when: not result.changed or result.failed
- name: Request certificate using an invalid profile
ipacert:
csr_file: "/root/user.csr"
principal: certuser
profile: invalid_profile
state: requested
register: result
failed_when: not (result.failed and "Request failed with status 400" in result.msg)
# CLEANUP TEST ITEMS
- name: Remove test user
ipauser:
name: certuser
state: absent
- name: Check retrieved certificate file
ansible.builtin.file:
path: "{{ item }}"
state: absent
with_items:
- "/root/retrieved.pem"
- "/root/cert_1.pem"
- "/root/user.csr"
ansible-freeipa-master/tests/config/ 0000775 0000000 0000000 00000000000 14600563364 0020013 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/config/test_config.yml 0000664 0000000 0000000 00000051455 14600563364 0023054 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle server configuration
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Execute config tests
block:
# Retrieve current configuration.
- name: Return current values of the global configuration options
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
register: previousconfig
- name: Display current configuration.
ansible.builtin.debug:
var: previousconfig
# setup environment.
- name: Create test group
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: somedefaultgroup
- name: Ensure the default e-mail domain is ipa.test.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
emaildomain: ipa.test
- name: Set default shell to '/bin/sh'
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
defaultshell: /bin/sh
- name: Set default group
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
defaultgroup: ipausers
- name: Set default home directory
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
homedirectory: /home
- name: Clear pac-type
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
pac_type: ""
- name: Execute tests if ipa_version >= 4.8.0
when: ipa_version is version('4.8.0', '>=')
block:
- name: Set maxhostname to 255
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxhostname: 255
- name: Set maxusername to 45
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxusername: 45
- name: Set pwdexpnotify to 0
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
pwdexpnotify: 0
- name: Set searchrecordslimit to 10
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
searchrecordslimit: 10
- name: Set searchtimelimit to 1
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
searchtimelimit: 1
- name: Clear configstring
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
configstring: ""
- name: Set configstring to AllowNThash
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
configstring: 'KDC:Disable Lockout'
- name: Set selinuxusermapdefault
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
selinuxusermapdefault: "staff_u:s0-s0:c0.c1023"
- name: Set selinuxusermaporder
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
selinuxusermaporder: 'user_u:s0$staff_u:s0-s0:c0.c1023'
- name: Set usersearch to `uid`
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
usersearch: uid
- name: Set groupsearch to `cn`
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
groupsearch: cn
# tests
- name: Ensure the default e-mail domain is somedomain.test.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
emaildomain: somedomain.test
register: result
failed_when: not result.changed or result.failed
- name: Ensure the default e-mail domain is somedomain.test, again.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
emaildomain: somedomain.test
register: result
failed_when: result.changed or result.failed
- name: Set default shell to '/bin/someshell'
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
defaultshell: /bin/someshell
register: result
failed_when: not result.changed or result.failed
- name: Set default shell to '/bin/someshell', again.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
defaultshell: /bin/someshell
register: result
failed_when: result.changed or result.failed
- name: Set default group
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
defaultgroup: somedefaultgroup
register: result
failed_when: not result.changed or result.failed
- name: Set default group, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
defaultgroup: somedefaultgroup
register: result
failed_when: result.changed or result.failed
- name: Set default home directory
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
homedirectory: /Users
register: result
failed_when: not result.changed or result.failed
- name: Set default home directory, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
homedirectory: /Users
register: result
failed_when: result.changed or result.failed
- name: Set pac-type
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
pac_type: "nfs:NONE"
register: result
failed_when: not result.changed or result.failed
- name: Set pac-type, again.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
pac_type: "nfs:NONE"
register: result
failed_when: result.changed or result.failed
- name: Set maxusername to 33
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxusername: 33
register: result
failed_when: not result.changed or result.failed
- name: Set maxusername to 33, again.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxusername: 33
register: result
failed_when: result.changed or result.failed
- name: Execute tests if ipa_version >= 4.8.0
when: ipa_version is version('4.8.0', '>=')
block:
- name: Set maxhostname to 77
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxhostname: 77
register: result
failed_when: not result.changed or result.failed
- name: Set maxhostname to 77, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxhostname: 77
register: result
failed_when: result.changed or result.failed
- name: Set pwdexpnotify to 17
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
pwdexpnotify: 17
register: result
failed_when: not result.changed or result.failed
- name: Set pwdexpnotify to 17, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
pwdexpnotify: 17
register: result
failed_when: result.changed or result.failed
- name: Set searchrecordslimit to -1
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
searchrecordslimit: -1
register: result
failed_when: not result.changed or result.failed
- name: Set searchrecordslimit to -1, again.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
searchrecordslimit: -1
register: result
failed_when: result.changed or result.failed
- name: Set searchtimelimit to 12345
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
searchtimelimit: 12345
register: result
failed_when: not result.changed or result.failed
- name: Set searchtimelimit to 12345, again.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
searchtimelimit: 12345
register: result
failed_when: result.changed or result.failed
- name: Change enable_migration
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
enable_migration: '{{ not (previousconfig.config.enable_migration | bool) }}'
register: result
failed_when: not result.changed or result.failed
- name: Change enable_migration, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
enable_migration: '{{ not (previousconfig.config.enable_migration | bool) }}'
register: result
failed_when: result.changed or result.failed
- name: Set configstring to AllowNThash
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
configstring: AllowNThash
register: result
failed_when: not result.changed or result.failed
- name: Set configstring to AllowNThash, again.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
configstring: AllowNThash
register: result
failed_when: result.changed or result.failed
- name: Set selinuxusermaporder
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
selinuxusermaporder: 'user_u:s0$staff_u:s0-s0:c0.c1023$sysadm_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023'
register: result
failed_when: not result.changed or result.failed
- name: Set selinuxusermaporder, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
selinuxusermaporder: 'user_u:s0$staff_u:s0-s0:c0.c1023$sysadm_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023'
register: result
failed_when: result.changed or result.failed
- name: Set selinuxusermapdefault
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
selinuxusermapdefault: 'user_u:s0'
register: result
failed_when: not result.changed or result.failed
- name: Set selinuxusermapdefault, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
selinuxusermapdefault: 'user_u:s0'
register: result
failed_when: result.changed or result.failed
- name: Set groupsearch to `description`
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
groupsearch: description
register: result
failed_when: not result.changed or result.failed
- name: Set groupsearch to `gidNumber`, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
groupsearch: description
register: result
failed_when: result.changed or result.failed
- name: Set usersearch to `uidNumber`
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
usersearch: uidNumber
register: result
failed_when: not result.changed or result.failed
- name: Set usersearch to `uidNumber`, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
usersearch: uidNumber
register: result
failed_when: result.changed or result.failed
- name: Reset changed fields
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxusername: '{{ previousconfig.config.maxusername | default(32) | int }}'
homedirectory: '{{ previousconfig.config.homedirectory | default(omit) }}'
defaultshell: '{{ previousconfig.config.defaultshell | default(omit) }}'
defaultgroup: '{{ previousconfig.config.defaultgroup | default(omit) }}'
emaildomain: '{{ previousconfig.config.emaildomain | default(omit) }}'
searchtimelimit: '{{ previousconfig.config.searchtimelimit | default(2) | int }}'
searchrecordslimit: '{{ previousconfig.config.searchrecordslimit | default(100) | int }}'
usersearch: '{{ previousconfig.config.usersearch | default(omit) }}'
groupsearch: '{{ previousconfig.config.groupsearch | default(omit) }}'
enable_migration: '{{ previousconfig.config.enable_migration | default(False) | bool }}'
groupobjectclasses: '{{ previousconfig.config.groupobjectclasses | default(omit) }}'
userobjectclasses: '{{ previousconfig.config.userobjectclasses | default(omit) }}'
pwdexpnotify: '{{ previousconfig.config.pwdexpnotify | default(4) | int }}'
configstring: '{{ previousconfig.config.configstring | default(omit) }}'
selinuxusermapdefault: '{{ previousconfig.config.selinuxusermapdefault | default(omit) }}'
selinuxusermaporder: '{{ previousconfig.config.selinuxusermaporder | default(omit) }}'
pac_type: '{{ previousconfig.config.pac_type | default(omit) }}'
user_auth_type: '{{ previousconfig.config.user_auth_type | default(omit) }}'
domain_resolution_order: '{{ previousconfig.config.domain_resolution_order | default(omit) }}'
ca_renewal_master_server: '{{ previousconfig.config.ca_renewal_master_server | default(omit) }}'
register: result
failed_when: not result.changed or result.failed
- name: Execute tests if ipa_version >= 4.8.0
when: ipa_version is version('4.8.0', '>=')
block:
- name: Reset maxhostname
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxhostname: '{{ previousconfig.config.maxhostname | default(omit) }}'
- name: Reset changed fields, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxusername: '{{ previousconfig.config.maxusername | default(omit) | int }}'
homedirectory: '{{ previousconfig.config.homedirectory | default(omit) }}'
defaultshell: '{{ previousconfig.config.defaultshell | default(omit) }}'
defaultgroup: '{{ previousconfig.config.defaultgroup | default(omit) }}'
emaildomain: '{{ previousconfig.config.emaildomain | default(omit) }}'
searchtimelimit: '{{ previousconfig.config.searchtimelimit | default(omit) | int }}'
searchrecordslimit: '{{ previousconfig.config.searchrecordslimit | default(omit) | int }}'
usersearch: '{{ previousconfig.config.usersearch | default(omit) }}'
groupsearch: '{{ previousconfig.config.groupsearch | default(omit) }}'
enable_migration: '{{ previousconfig.config.enable_migration | default(omit) | bool }}'
groupobjectclasses: '{{ previousconfig.config.groupobjectclasses | default(omit) }}'
userobjectclasses: '{{ previousconfig.config.userobjectclasses | default(omit) }}'
pwdexpnotify: '{{ previousconfig.config.pwdexpnotify | default(omit) | int }}'
configstring: '{{ previousconfig.config.configstring | default(omit) }}'
selinuxusermapdefault: '{{ previousconfig.config.selinuxusermapdefault | default(omit) }}'
selinuxusermaporder: '{{ previousconfig.config.selinuxusermaporder | default(omit) }}'
pac_type: '{{ previousconfig.config.pac_type | default(omit) }}'
user_auth_type: '{{ previousconfig.config.user_auth_type | default(omit) }}'
domain_resolution_order: '{{ previousconfig.config.domain_resolution_order | default(omit) }}'
ca_renewal_master_server: '{{ previousconfig.config.ca_renewal_master_server | default(omit) }}'
register: result
failed_when: result.changed or result.failed
- name: Execute tests if ipa_version >= 4.8.0
when: ipa_version is version('4.8.0', '>=')
block:
- name: Reset maxhostname
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxhostname: '{{ previousconfig.config.maxhostname | default(omit) }}'
rescue:
- name: Set fields to IPA default, due to error
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxusername: '{{ previousconfig.config.maxusername | default(omit) | int }}'
homedirectory: '{{ previousconfig.config.homedirectory | default(omit) }}'
defaultshell: '{{ previousconfig.config.defaultshell | default(omit) }}'
defaultgroup: '{{ previousconfig.config.defaultgroup | default(omit) }}'
emaildomain: '{{ previousconfig.config.emaildomain | default(omit) }}'
searchtimelimit: '{{ previousconfig.config.searchtimelimit | default(omit) | int }}'
searchrecordslimit: '{{ previousconfig.config.searchrecordslimit | default(omit) | int }}'
usersearch: '{{ previousconfig.config.usersearch | default(omit) }}'
groupsearch: '{{ previousconfig.config.groupsearch | default(omit) }}'
enable_migration: '{{ previousconfig.config.enable_migration | default(omit) | bool }}'
groupobjectclasses: '{{ previousconfig.config.groupobjectclasses | default(omit) }}'
userobjectclasses: '{{ previousconfig.config.userobjectclasses | default(omit) }}'
pwdexpnotify: '{{ previousconfig.config.pwdexpnotify | default(omit) | int }}'
configstring: '{{ previousconfig.config.configstring | default(omit) }}'
selinuxusermapdefault: '{{ previousconfig.config.selinuxusermapdefault | default(omit) }}'
selinuxusermaporder: '{{ previousconfig.config.selinuxusermaporder | default(omit) }}'
pac_type: '{{ previousconfig.config.pac_type | default(omit) }}'
user_auth_type: '{{ previousconfig.config.user_auth_type | default(omit) }}'
domain_resolution_order: '{{ previousconfig.config.domain_resolution_order | default(omit) }}'
ca_renewal_master_server: '{{ previousconfig.config.ca_renewal_master_server | default(omit) }}'
register: result
- name: "CA-Renewal server warning."
ansible.builtin.debug:
msg: "Due to a test failure, IPA CA-Renewal Server might not be correctly be set. Check your configuration."
always:
# cleanup
- name: Cleanup test group
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: somedefaultgroup
state: absent
ansible-freeipa-master/tests/config/test_config_client_context.yml 0000664 0000000 0000000 00000002355 14600563364 0026151 0 ustar 00root root 0000000 0000000 ---
- name: Test config
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test config using client context, in client host.
ansible.builtin.import_playbook: test_config.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test config using client context, in server host.
ansible.builtin.import_playbook: test_config.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/config/test_config_empty_string_params.yml 0000664 0000000 0000000 00000010570 14600563364 0027214 0 ustar 00root root 0000000 0000000 ---
- name: Test config
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: yes
gather_facts: no
tasks:
# GET CURRENT CONFIG
- name: Return current values of the global configuration options
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
register: previousconfig
- name: Ensure config with empty pac_type, user_auth_type and configstring
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
pac_type: ""
user_auth_type: ""
configstring: ""
# TESTS
- name: Ensure config with pac_type "nfs:NONE" and PAD
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
pac_type:
- "nfs:NONE"
- PAD
register: result
failed_when: not result.changed or result.failed
- name: Ensure config with pac_type "nfs:NONE" and PAD, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
pac_type:
- "nfs:NONE"
- PAD
register: result
failed_when: result.changed or result.failed
- name: Ensure config with empty pac_type
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
pac_type: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure config with empty pac_type, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
pac_type: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure config with user_auth_type otp and radius
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
user_auth_type:
- otp
- radius
register: result
failed_when: not result.changed or result.failed
- name: Ensure config with user_auth_type otp and radius, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
user_auth_type:
- otp
- radius
register: result
failed_when: result.changed or result.failed
- name: Ensure config with empty user_auth_type
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
user_auth_type: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure config with empty user_auth_type, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
user_auth_type: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure config with configstring AllowNThash and "KDC:Disable Lockout"
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
configstring:
- AllowNThash
- "KDC:Disable Lockout"
register: result
failed_when: not result.changed or result.failed
- name: Ensure config with configstring AllowNThash and "KDC:Disable Lockout", again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
configstring:
- AllowNThash
- "KDC:Disable Lockout"
register: result
failed_when: result.changed or result.failed
- name: Ensure config with empty configstring
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
configstring: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure config with empty configstring, again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
configstring: ""
register: result
failed_when: result.changed or result.failed
# REVERT TO PREVIOUS CONFIG
- name: Reset to previous pac_type and user_auth_type
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
pac_type: '{{ previousconfig.config.pac_type }}'
user_auth_type: '{{ previousconfig.config.user_auth_type }}'
configstring: '{{ previousconfig.config.configstring }}'
ansible-freeipa-master/tests/config/test_config_sid.yml 0000664 0000000 0000000 00000010671 14600563364 0023706 0 ustar 00root root 0000000 0000000 ---
- name: Test config
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
tasks:
- name: Set FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# GET CURRENT CONFIG
- name: Return current values of the global configuration options
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
register: previous
# TESTS
- name: Test config sid
# only run tests if version supports enable-sid
when: ipa_version is version("4.9.8", ">=")
block:
- name: Check if SID is enabled.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
enable_sid: yes
check_mode: yes
register: sid_disabled
- name: Ensure netbios_name can't be changed without SID enabled. # noqa no-handler
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
netbios_name: IPATESTPLAY
register: result
failed_when: not result.failed and "SID generation must be enabled" in result.msg
when: sid_disabled.changed
- name: Ensure SIDs can't be changed without SID enabled. # noqa no-handler
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
add_sids: yes
register: result
failed_when: not result.failed and "SID generation must be enabled" in result.msg
when: sid_disabled.changed
- name: Ensure SID is enabled.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
enable_sid: yes
register: result
failed_when: result.failed or previous.config.enable_sid == result.changed
- name: Ensure SID is enabled, again.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
enable_sid: yes
register: result
failed_when: result.failed or result.changed
- name: Try to Ensure SID is disabled.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
enable_sid: no
register: result
failed_when: not result.failed or "SID cannot be disabled." not in result.msg
- name: Ensure netbios_name is "IPATESTPLAY"
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
enable_sid: yes
netbios_name: IPATESTPLAY
register: result
failed_when: result.failed or not result.changed
- name: Ensure netbios_name is "IPATESTPLAY", again
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
netbios_name: IPATESTPLAY
register: result
failed_when: result.failed or result.changed
- name: Ensure netbios_name cannot be set with lowercase characters
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
netbios_name: IPATESTplay
register: result
failed_when:
(not result.failed
and "Up to 15 characters and only uppercase ASCII letters, digits and dashes are allowed" not in result.message)
- name: Ensure netbios_name cannot be set different lowercase characters
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
netbios_name: otherPLAY
register: result
failed_when:
(not result.failed
and "Up to 15 characters and only uppercase ASCII letters, digits and dashes are allowed" not in result.message)
# add_sids is not idempotent as it always tries to generate the missing
# SIDs for users and groups.
- name: Add SIDs to users and groups.
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
add_sids: yes
# REVERT TO PREVIOUS CONFIG
always:
# Once SID is enabled, it cannot be reverted.
- name: Revert netbios_name to original configuration
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
netbios_name: "{{ previous.config.netbios_name | default(omit) }}"
enable_sid: yes
ansible-freeipa-master/tests/delegation/ 0000775 0000000 0000000 00000000000 14600563364 0020661 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/delegation/test_delegation.yml 0000664 0000000 0000000 00000023077 14600563364 0024567 0 ustar 00root root 0000000 0000000 ---
- name: Test delegation
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
# CLEANUP TEST ITEMS
- name: Ensure test groups are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: managers,managers2,employees,employees2
state: absent
- name: Ensure delegation "basic manager attributes" is absent
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
state: absent
# CREATE TEST ITEMS
- name: Ensure test group managers is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: managers
- name: Ensure test group managers2 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: managers2
- name: Ensure test group employees is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: employees
- name: Ensure test group employees2 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: employees2
# TESTS
- name: Ensure delegation "basic manager attributes" is present
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
group: managers
membergroup: employees
register: result
failed_when: not result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present again
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
group: managers
membergroup: employees
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present with different attribute employeetype
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- employeetype
group: managers
membergroup: employees
register: result
failed_when: not result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present with different attribute employeetype again
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- employeetype
group: managers
membergroup: employees
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" member attribute departmentnumber is present
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
attribute:
- departmentnumber
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure delegation "basic manager attributes" member attribute departmentnumber is present again
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
attribute:
- departmentnumber
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" member attributes employeetype and employeenumber are present
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
attribute:
- employeetype
- employeenumber
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure delegation "basic manager attributes" member attributes employeetype and employeenumber are present again
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
attribute:
- employeetype
- employeenumber
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" member attributes employeenumber and employeetype are absent
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
attribute:
- employeenumber
- employeetype
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure delegation "basic manager attributes" member attributes employeenumber and employeetype are absent again
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
attribute:
- employeenumber
- employeetype
action: member
state: absent
register: result
failed_when: result.changed or result.failed
# TEST permission change
- name: Ensure delegation "basic manager attributes" is present with different read,write permission
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read,write
attribute:
- businesscategory
group: managers
membergroup: employees
register: result
failed_when: not result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present with different read,write permission again
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read,write
attribute:
- businesscategory
group: managers
membergroup: employees
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present with different group managers2
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
group: managers2
register: result
failed_when: not result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present with different group managers2 again
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
group: managers2
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present with different membergroup employees2
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
membergroup: employees2
register: result
failed_when: not result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present with different membergroup employees2 again
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
membergroup: employees2
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" fails with bad permission read,read
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read,read
register: result
failed_when: not result.failed or "Invalid permission" not in result.msg
- name: Ensure delegation "basic manager attributes" fails with bad permission read,write,write
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read,write,write
register: result
failed_when: not result.failed or "Invalid permission" not in result.msg
- name: Ensure delegation "basic manager attributes" fails with bad attribute businesscategory,businesscategory
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
attribute:
- businesscategory
- businesscategory
register: result
failed_when: not result.failed or "Invalid attribute" not in result.msg
# CLEANUP TEST ITEMS
- name: Ensure delegation "basic manager attributes" is absent
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
state: absent
- name: Ensure test groups are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: managers,managers2,employees,employees2
state: absent
ansible-freeipa-master/tests/delegation/test_delegation_client_context.yml 0000664 0000000 0000000 00000002443 14600563364 0027663 0 ustar 00root root 0000000 0000000 ---
- name: Test delegation
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test delegation using client context, in client host.
ansible.builtin.import_playbook: test_delegation.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test delegation using client context, in server host.
ansible.builtin.import_playbook: test_delegation.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/delegation/test_delegation_member_case_insensitive.yml 0000664 0000000 0000000 00000020051 14600563364 0031516 0 ustar 00root root 0000000 0000000 ---
- name: Test delegation
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
tasks:
- name: Test different cases for string case.
block:
# CLEANUP TEST ITEMS
- name: Ensure delegation "basic manager attributes" is absent
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
state: absent
# CREATE TEST ITEMS
- name: Ensure test group managers is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: managers
- name: Ensure test group employees is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: employees
# TESTS
- name: Ensure delegation "basic manager attributes" is present, group/membergroup mixed case
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
group: Managers
membergroup: Employees
register: result
failed_when: not result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present, group lowercase
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
group: "{{ 'Managers' | lower }}"
membergroup: Employees
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present, group uppercase
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
group: "{{ 'Managers' | upper }}"
membergroup: Employees
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present, permission upercase
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: "{{ 'read' | upper }}"
attribute:
- businesscategory
group: managers
membergroup: Employees
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present, permission mixed case
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: Read
attribute:
- businesscategory
group: managers
membergroup: Employees
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present, attribute upercase
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- "{{ 'businesscategory' | upper }}"
group: managers
membergroup: Employees
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present, attribute mixed case
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- BusinessCategory
group: managers
membergroup: Employees
register: result
failed_when: result.changed or result.failed
# membergroup does not use case insensitive comparison
- name: Ensure delegation "basic manager attributes" is present, membergroup lowercase
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
group: managers
membergroup: "{{ 'Employees' | lower }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present, membergroup uppercase
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
group: managers
membergroup: "{{ 'Employees' | upper }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure delegation "basic manager attributes" is present, group/membergroup mixed case
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
group: Managers
membergroup: Employees
register: result
failed_when: not result.changed or result.failed
# tests for action: member
- name: Ensure delegation "basic manager attributes" is present, with group and attribute in mixed case
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- BusinessCategory
group: Managers
membergroup: Employees
- name: Ensure delegation "basic manager attributes" is present, attribute mixed case
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
permission: read
attribute:
- BusinessCategory
group: managers
membergroup: employees
- name: Ensure delegation "basic manager attributes" member is present, attribute upercase
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
attribute:
- "{{ 'BusinessCategory' | upper }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure delegation "basic manager attributes" member is present, attribute lowercase
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
attribute:
- "{{ 'BusinessCategory' | lower }}"
action: member
register: result
failed_when: result.changed or result.failed
always:
# CLEANUP TEST ITEMS
- name: Ensure delegation "basic manager attributes" is absent
ipadelegation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "basic manager attributes"
state: absent
- name: Ensure test groups are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: managers,employees
state: absent
ansible-freeipa-master/tests/dnsconfig/ 0000775 0000000 0000000 00000000000 14600563364 0020520 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/dnsconfig/test_dnsconfig.yml 0000664 0000000 0000000 00000013662 14600563364 0024264 0 ustar 00root root 0000000 0000000 ---
- name: Test dnsconfig
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: true
tasks:
# Setup.
- name: Ensure forwarders are absent.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.8.8
- ip_address: 8.8.4.4
state: absent
action: member
# Tests.
- name: Set forward with invalid IPv4.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 1.2.3.500
register: result
failed_when: not result.failed or "Invalid IP for DNS forwarder" not in result.msg
- name: Set config to invalid IP.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 1.in.va.lid
register: result
failed_when: not result.failed or "Invalid IP for DNS forwarder" not in result.msg
- name: Set config to invalid IPv6.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: fd00::invalid
register: result
failed_when: not result.failed or "Invalid IP for DNS forwarder" not in result.msg
- name: Set dnsconfig.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.8.8
- ip_address: 8.8.4.4
forward_policy: only
allow_sync_ptr: yes
register: result
failed_when: not result.changed or result.failed
- name: Set dnsconfig, with the same values.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.8.8
- ip_address: 8.8.4.4
forward_policy: only
allow_sync_ptr: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure forwarder 8.8.8.8 is absent.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.8.8
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure forwarder 8.8.8.8 is absent, again.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.8.8
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: Check if forwarder 8.8.4.4 is present.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.4.4
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure forwarder 8.8.8.8 is present.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.8.8
register: result
failed_when: not result.changed or result.failed
- name: Check forwarder 8.8.4.4 is still present.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.4.4
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Disable global forwarders.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forward_policy: none
register: result
failed_when: not result.changed or result.failed
- name: Disable global forwarders, again.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forward_policy: none
register: result
failed_when: result.changed or result.failed
- name: Re-enable global forwarders.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forward_policy: first
register: result
failed_when: not result.changed or result.failed
- name: Re-enable global forwarders, again.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forward_policy: first
register: result
failed_when: result.changed or result.failed
- name: Disable PTR record synchronization.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
allow_sync_ptr: no
register: result
failed_when: not result.changed or result.failed
- name: Disable PTR record synchronization, again.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
allow_sync_ptr: no
register: result
failed_when: result.changed or result.failed
- name: Re-enable PTR record synchronization.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
allow_sync_ptr: yes
register: result
failed_when: not result.changed or result.failed
- name: Re-enable PTR record synchronization, again.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
allow_sync_ptr: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure forwarders are absent.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.8.8
- ip_address: 8.8.4.4
state: absent
action: member
ansible-freeipa-master/tests/dnsconfig/test_dnsconfig_client_context.yml 0000664 0000000 0000000 00000002432 14600563364 0027357 0 ustar 00root root 0000000 0000000 ---
- name: Test dnsconfig
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
forward_policy: none
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test dnsconfig using client context, in client host.
ansible.builtin.import_playbook: test_dnsconfig.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test dnsconfig using client context, in server host.
ansible.builtin.import_playbook: test_dnsconfig.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/dnsconfig/test_dnsconfig_forwarders_ports.yml 0000664 0000000 0000000 00000004643 14600563364 0027750 0 ustar 00root root 0000000 0000000 ---
- name: Test dnsconfig forwarders with custom ports
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: no
tasks:
- name: Test dnsconfig forwarders ports
block:
# Setup.
- name: Ensure forwarder with custom port is absent.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 2001:4860:4860::8888
port: 53
state: absent
action: member
# Tests.
- name: Ensure forwarder with custom port is present.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 2001:4860:4860::8888
port: 53
state: present
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure forwarder with custom port is present, again.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 2001:4860:4860::8888
port: 53
state: present
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure forwarder with custom port is absent.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 2001:4860:4860::8888
port: 53
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure forwarder with custom port is absent, again.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 2001:4860:4860::8888
port: 53
state: absent
action: member
register: result
failed_when: result.changed or result.failed
always:
# Cleanup.
- name: Ensure forwarder with custom port is absent.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 2001:4860:4860::8888
port: 53
state: absent
action: member
ansible-freeipa-master/tests/dnsforwardzone/ 0000775 0000000 0000000 00000000000 14600563364 0021613 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/dnsforwardzone/test_dnsforwardzone.yml 0000664 0000000 0000000 00000027033 14600563364 0026447 0 ustar 00root root 0000000 0000000 ---
- name: Test dnsforwardzone
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
- name: Ensure test forwardzones are absent
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- example.com
- newfailzone.com
state: absent
- name: Ensure forwardzone example.com is created
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: present
name: example.com
forwarders:
- ip_address: 8.8.8.8
forwardpolicy: first
skip_overlap_check: true
register: result
failed_when: not result.changed or result.failed
- name: Ensure forwardzone example.com is present again
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: present
name: example.com
forwarders:
- ip_address: 8.8.8.8
forwardpolicy: first
skip_overlap_check: true
register: result
failed_when: result.changed or result.failed
- name: Ensure forwardzone example.com has two forwarders
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: present
name: example.com
forwarders:
- ip_address: 8.8.8.8
- ip_address: 4.4.4.4
port: 8053
forwardpolicy: first
skip_overlap_check: true
register: result
failed_when: not result.changed or result.failed
- name: Ensure forwardzone example.com has one forwarder again
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
forwarders:
- ip_address: 8.8.8.8
forwardpolicy: first
skip_overlap_check: true
state: present
register: result
failed_when: result.changed or result.failed
- name: Skip_overlap_check can only be set on creation so change nothing
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
forwarders:
- ip_address: 8.8.8.8
forwardpolicy: first
skip_overlap_check: false
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure forwardzone example.com is absent.
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure forwardzone example.com is absent, again.
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
state: absent
register: result
failed_when: result.changed or result.failed
- name: Change all the things at once
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: present
name: example.com
forwarders:
- ip_address: 8.8.8.8
- ip_address: 4.4.4.4
port: 8053
forwardpolicy: only
skip_overlap_check: true
permission: yes
register: result
failed_when: not result.changed or result.failed
- name: Change zone forward policy
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
forwardpolicy: first
register: result
failed_when: not result.changed or result.failed
- name: Change zone forward policy, again
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
forwardpolicy: first
register: result
failed_when: result.changed or result.failed
- name: Ensure forwardzone example.com is absent.
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure forwardzone example.com is absent, again.
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure forwardzone example.com is created with minimal args
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: present
name: example.com
skip_overlap_check: true
forwarders:
- ip_address: 8.8.8.8
register: result
failed_when: not result.changed or result.failed
- name: Ensure forwardzone example.com is created with minimal args, again
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: present
name: example.com
skip_overlap_check: true
forwarders:
- ip_address: 8.8.8.8
register: result
failed_when: result.changed or result.failed
- name: Add a forwarder to any existing ones
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: present
name: example.com
forwarders:
- ip_address: 4.4.4.4
port: 8053
action: member
register: result
failed_when: not result.changed or result.failed
- name: Add a forwarder to any existing ones, again
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: present
name: example.com
forwarders:
- ip_address: 4.4.4.4
port: 8053
action: member
register: result
failed_when: result.changed or result.failed
- name: Check the list of forwarders is what we expect
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: present
name: example.com
forwarders:
- ip_address: 4.4.4.4
port: 8053
- ip_address: 8.8.8.8
action: member
register: result
failed_when: result.changed or result.failed
- name: Remove a single forwarder
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: absent
name: example.com
forwarders:
- ip_address: 8.8.8.8
action: member
register: result
failed_when: not result.changed or result.failed
- name: Remove a single forwarder, again
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: absent
name: example.com
forwarders:
- ip_address: 8.8.8.8
action: member
register: result
failed_when: result.changed or result.failed
- name: Check the list of forwarders is what we expect now
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: present
name: example.com
forwarders:
- ip_address: 4.4.4.4
port: 8053
action: member
register: result
failed_when: result.changed or result.failed
- name: Add a permission for per-forward zone access delegation.
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
permission: yes
action: member
register: result
failed_when: not result.changed or result.failed
- name: Add a permission for per-forward zone access delegation, again.
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
permission: yes
action: member
register: result
failed_when: result.changed or result.failed
- name: Remove a permission for per-forward zone access delegation.
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
permission: no
action: member
register: result
failed_when: not result.changed or result.failed
- name: Remove a permission for per-forward zone access delegation, again.
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
permission: no
action: member
register: result
failed_when: result.changed or result.failed
- name: Disable the forwarder
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
state: disabled
register: result
failed_when: not result.changed or result.failed
- name: Disable the forwarder again
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
state: disabled
register: result
failed_when: result.changed or result.failed
- name: Enable the forwarder
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
state: enabled
register: result
failed_when: not result.changed or result.failed
- name: Enable the forwarder, again
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
state: enabled
register: result
failed_when: result.changed or result.failed
- name: Ensure forwardzone example.com is absent again
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
state: absent
- name: Try to create a new forwarder with action=member
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: present
name: example.com
forwarders:
- ip_address: 4.4.4.4
port: 8053
action: member
skip_overlap_check: true
register: result
failed_when: not result.failed or "not found" not in result.msg
- name: Try to create a new forwarder with disabled state
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: example.com
state: disabled
register: result
failed_when: not result.failed or "not found" not in result.msg
- name: Ensure forwardzone is not added without forwarders, with correct message.
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: newfailzone.com
register: result
failed_when: not result.failed or "No forwarders specified" not in result.msg
- name: Ensure forwardzone example.com is absent - tidy up
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- example.com
- newfailzone.com
state: absent
ansible-freeipa-master/tests/dnsforwardzone/test_dnsforwardzone_client_context.yml 0000664 0000000 0000000 00000002473 14600563364 0031552 0 ustar 00root root 0000000 0000000 ---
- name: Test dnsforwardzone
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test dnsforwardzone using client context, in client host.
ansible.builtin.import_playbook: test_dnsforwardzone.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test dnsforwardzone using client context, in server host.
ansible.builtin.import_playbook: test_dnsforwardzone.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/dnsrecord/ 0000775 0000000 0000000 00000000000 14600563364 0020531 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/dnsrecord/env_cleanup.yml 0000664 0000000 0000000 00000010352 14600563364 0023554 0 ustar 00root root 0000000 0000000 ---
# Cleanup tasks.
- name: Ensure that dns records are absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
del_all: yes
name:
- host01
- host02
- host03
- host04
- _ftp._tcp
- _sip._udp
state: absent
- name: Ensure that dns reverse ipv6 records are absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: ip6.arpa.
del_all: yes
name:
- 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f
- 1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f
- 1.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f
- 4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f
- 4.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f
- 4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f
state: absent
- name: Ensure that dns reverse ipv6 records are absent (workaround)
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ zone_ipv6_reverse_workaround }}"
del_all: yes
name:
- 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
- 1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
- 1.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
- 4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
- 4.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
- 4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0
state: absent
- name: Ensure that dns reverse records are absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ zone_prefix_reverse_24 }}"
name:
- "101"
- "102"
- "103"
- "104"
- "111"
- "112"
- "113"
- "114"
- "121"
- "122"
- "123"
- "124"
del_all: yes
state: absent
- name: Ensure that dns reverse records are absent (workaround 1)
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ zone_prefix_reverse_16 }}"
name:
- "101.122"
- "102.122"
- "103.122"
- "104.122"
- "111.122"
- "112.122"
- "113.122"
- "114.122"
- "121.122"
- "122.122"
- "123.122"
- "124.122"
del_all: yes
state: absent
- name: Ensure that dns reverse records are absent (workaround 2)
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ zone_prefix_reverse_8 }}"
name:
- "168.101.122"
- "168.102.122"
- "168.103.122"
- "168.104.122"
- "168.111.122"
- "168.112.122"
- "168.113.122"
- "168.114.122"
- "168.121.122"
- "168.122.122"
- "168.123.122"
- "168.124.122"
del_all: yes
state: absent
- name: Ensure that "{{ safezone }}" dns records are absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ safezone }}"
records:
- name: iron01
del_all: yes
state: absent
- name: Ensure that NS record for "{{ safezone }}" is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: iron01
zone_name: "{{ safezone }}"
ns_rec: iron01
state: absent
- name: Ensure DNS testing zones are absent.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ item }}"
state: absent
with_items:
- "{{ zone_prefix_reverse }}"
- "{{ zone_prefix_reverse_24 }}"
- "{{ zone_prefix_reverse_16 }}"
- "{{ zone_prefix_reverse_8 }}"
- "{{ zone_ipv6_reverse }}"
- "{{ zone_ipv6_reverse_workaround }}"
- "{{ testzone }}"
- "{{ safezone }}"
ansible-freeipa-master/tests/dnsrecord/env_setup.yml 0000664 0000000 0000000 00000002003 14600563364 0023257 0 ustar 00root root 0000000 0000000 ---
- name: Setup variables and facts.
ansible.builtin.include_tasks: env_vars.yml
# Cleanup before setup.
- name: Cleanup test environment.
ansible.builtin.include_tasks: env_cleanup.yml
# Common setup tasks.
- name: Ensure DNS testing zones are present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ item }}"
skip_nameserver_check: yes
skip_overlap_check: yes
with_items:
- "{{ zone_prefix_reverse }}"
- "{{ zone_prefix_reverse_24 }}"
- "{{ zone_prefix_reverse_16 }}"
- "{{ zone_prefix_reverse_8 }}"
- "{{ zone_ipv6_reverse_workaround }}"
- "{{ testzone }}"
- "{{ zone_ipv6_reverse }}"
- name: Ensure DNSSEC zone '"{{ safezone }}"' is present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ safezone }}"
dnssec: yes
skip_nameserver_check: yes
skip_overlap_check: yes
ansible-freeipa-master/tests/dnsrecord/env_vars.yml 0000664 0000000 0000000 00000001547 14600563364 0023106 0 ustar 00root root 0000000 0000000 ---
# Set common vars and facts for test.
- name: Set IPv4 address prefix.
ansible.builtin.set_fact:
ipv4_prefix: "{{ ansible_facts['default_ipv4'].address.split('.')[:-1] |
join('.') }}"
ipv4_reverse: "{{ ansible_facts['default_ipv4'].address.split('.')[:-1] |
reverse |
join('.') }}"
- name: Set zone prefixes.
ansible.builtin.set_fact:
testzone: 'testzone.test'
safezone: 'safezone.test'
zone_ipv6_reverse: "ip6.arpa."
zone_ipv6_reverse_workaround: "d.f.ip6.arpa."
zone_prefix_reverse: "in-addr.arpa."
zone_prefix_reverse_24: "{{ ipv4_reverse.split('.')[:] | join('.') }}.in-addr.arpa."
zone_prefix_reverse_16: "{{ ipv4_reverse.split('.')[1:] | join('.') }}.in-addr.arpa."
zone_prefix_reverse_8: "{{ ipv4_reverse.split('.')[2:] | join('.') }}.in-addr.arpa."
ansible-freeipa-master/tests/dnsrecord/test_compatibility_with_ansible_module.yml 0000664 0000000 0000000 00000016606 14600563364 0031272 0 ustar 00root root 0000000 0000000 ---
- name: Test compatibility with Ansible ipa_dnsrecord module.
hosts: ipaserver
become: true
gather_facts: false
tasks:
# setup
- name: Ensure DNS zones to be used are absent.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
with_items:
- testzone.local
- 2.168.192.in-addr.arpa
- name: Ensure DNS zones to be used are present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
with_items:
- testzone.local
- 2.168.192.in-addr.arpa
- name: Ensure that dns record 'host01' is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: testzone.local
del_all: yes
state: absent
- name: Ensure that dns records for 'vm-001' are absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: vm-001
zone_name: testzone.local
del_all: yes
state: absent
- name: Ensure a PTR record is absent for 'vm-001'
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: '1'
record_type: 'PTR'
record_value: 'vm-001'
zone_name: 2.168.192.in-addr.arpa
state: absent
- name: Ensure a PTR record is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: 2.168.192.in-addr.arpa
name: "5"
del_all: yes
state: absent
- name: Ensure a TXT record is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: _kerberos
record_type: 'TXT'
record_value: 'TESTZONE.LOCAL'
zone_name: testzone.local
state: absent
- name: Ensure a SRV record is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: _kerberos._udp.testzone.local
record_type: 'SRV'
record_value: '10 50 88 ipa.testzone.local'
zone_name: testzone.local
state: absent
- name: Ensure an MX record is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: '@'
record_type: 'MX'
record_value: '1 mailserver.testzone.local'
zone_name: testzone.local
state: absent
# tests
- name: Ensure AAAA dns record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: vm-001
record_type: 'AAAA'
record_value: '::1'
zone_name: testzone.local
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure that AAAA dns record exists with a TTL
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
record_type: 'AAAA'
record_value: '::1'
record_ttl: 300
zone_name: testzone.local
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure a PTR record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: '5'
record_type: 'PTR'
record_value: 'internal.ipa.testzone.local'
zone_name: 2.168.192.in-addr.arpa
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure A record is present, with reverse
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: vm-001
record_type: 'A'
record_value: '192.168.2.1'
create_reverse: yes
zone_name: testzone.local
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure A record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: vm-001
record_type: 'A'
record_value: '192.168.2.1'
zone_name: testzone.local
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure PTR record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: '1'
record_type: 'PTR'
record_value: vm-001.testzone.local
zone_name: 2.168.192.in-addr.arpa
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure a TXT record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: _kerberos
record_type: 'TXT'
record_value: 'TESTZONE.LOCAL'
zone_name: testzone.local
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure a SRV record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: _kerberos._udp.testzone.local
record_type: 'SRV'
record_value: '10 50 88 ipa.testzone.local'
zone_name: testzone.local
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure an MX record is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: '@'
record_type: 'MX'
record_value: '1 mailserver.testzone.local'
zone_name: testzone.local
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure that dns record is removed
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: testzone.local
record_type: 'AAAA'
record_value: '::1'
state: absent
register: result
failed_when: not result.changed or result.failed
# cleanup
- name: Ensure that dns record 'host01' is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: testzone.local
record_type: 'AAAA'
record_value: '::1'
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that dns record 'vm-001' is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: vm-001
zone_name: testzone.local
record_type: 'AAAA'
record_value: '::1'
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure a PTR record is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: 5
record_type: 'PTR'
record_value: 'internal.ipa.testzone.local'
zone_name: 2.168.192.in-addr.arpa
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure a TXT record is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: _kerberos
record_type: 'TXT'
record_value: 'TESTZONE.LOCAL'
zone_name: testzone.local
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure a SRV record is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: _kerberos._udp.testzone.local
record_type: 'SRV'
record_value: '10 50 88 ipa.testzone.local'
zone_name: testzone.local
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure an MX record is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: '@'
record_type: 'MX'
record_value: '1 mailserver.testzone.local'
zone_name: testzone.local
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure DNS zones to be used are absent.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
with_items:
- testzone.local
- 2.168.192.in-addr.arpa
ansible-freeipa-master/tests/dnsrecord/test_dnsrecord.yml 0000664 0000000 0000000 00000147255 14600563364 0024314 0 ustar 00root root 0000000 0000000 ---
- name: Test dnsrecord
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: yes
gather_facts: yes
tasks:
- name: Setup testing environment.
ansible.builtin.include_tasks: env_setup.yml
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [1]
become: no
delegate_to: localhost
# tests
- name: Ensure that dns record 'host01' is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: host01
zone_name: "{{ testzone }}"
record_type: AAAA
record_value: ::1
register: result
failed_when: not result.changed or result.failed
- name: Ensure that dns record 'host01' is present, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: host01
zone_name: "{{ testzone }}"
record_type: AAAA
record_value: ::1
register: result
failed_when: result.changed or result.failed
- name: Ensure that dns record 'host02' is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: host02
zone_name: "{{ testzone }}"
record_type: A
record_value: "{{ ipv4_prefix }}.102"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that dns record 'host02' is present, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: host02
zone_name: "{{ testzone }}"
record_type: A
record_value: "{{ ipv4_prefix }}.102"
register: result
failed_when: result.changed or result.failed
- name: Modify record 'host02' with multiple A and AAAA record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
records:
- name: host02
zone_name: "{{ testzone }}"
record_type: A
record_value:
- "{{ ipv4_prefix }}.112"
- "{{ ipv4_prefix }}.122"
- name: host02
zone_name: "{{ testzone }}"
record_type: AAAA
record_value: ::1
register: result
failed_when: not result.changed or result.failed
- name: Modify record 'host02' with multiple A and AAAA record, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
records:
- name: host02
zone_name: "{{ testzone }}"
record_type: A
record_value:
- "{{ ipv4_prefix }}.112"
- "{{ ipv4_prefix }}.122"
- name: host02
zone_name: "{{ testzone }}"
record_type: AAAA
record_value: ::1
register: result
failed_when: result.changed or result.failed
- name: Ensure 'host02' A6 record is present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host02
a6_data: ::1
register: result
failed_when: not result.changed or result.failed
- name: Ensure 'host02' A6 record is present, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host02
a6_rec: ::1
register: result
failed_when: result.changed or result.failed
- name: Ensure 'host02' A6 record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host02
a6_rec: ::1
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure 'host02' A6 record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host02
a6_rec: ::1
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that dns record 'host03' is present, with reverse record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: host03
zone_name: "{{ testzone }}"
a_ip_address: "{{ ipv4_prefix }}.103"
a_create_reverse: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure that dns record 'host03' is present, with reverse record, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: host03
zone_name: "{{ testzone }}"
record_type: A
record_value: "{{ ipv4_prefix }}.103"
create_reverse: yes
register: result
failed_when: result.changed or result.failed
- name: Delete all entries associated with host03
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host03
del_all: yes
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Delete all entries associated with host03, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host03
del_all: yes
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' has CNAME
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
record_type: CNAME
record_value: "host04.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' has CNAME, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
cname_hostname: "host04.{{ testzone }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' CNAME is absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
cname_rec: "host04.{{ testzone }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' CNAME is absent, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
record_type: CNAME
record_value: "host04.{{ testzone }}"
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' and 'host03' have CNAME, with cname_hostname
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
records:
- name: host04
cname_hostname: "host04.{{ testzone }}"
- name: host03
cname_hostname: "host03.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' has CNAME, with cname_hostname, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
cname_hostname: "host04.{{ testzone }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' CNAME is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
cname_rec: "host04.{{ testzone }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' has A record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
ip_address: "{{ ipv4_prefix }}.104"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' has A record, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
ip_address: "{{ ipv4_prefix }}.104"
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' has the same A record with reverse.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
a_rec: "{{ ipv4_prefix }}.104"
reverse: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' has the same A record with reverse, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
a_rec: "{{ ipv4_prefix }}.104"
reverse: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' has another A record with reverse.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
ip_address: "{{ ipv4_prefix }}.114"
reverse: yes
failed_when: result.changed or result.failed
- name: Ensure that 'host04' has another A record with reverse, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
ip_address: "{{ ipv4_prefix }}.114"
reverse: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' has AAAA record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
aaaa_ip_address: fd00::0004
aaaa_create_reverse: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' has AAAA record, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
ip_address: fd00::0004
reverse: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' has AAAA record, without reverse.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
ip_address: fd00::0014
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' previous AAAA record, now has a reverse record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
aaaa_rec: fd00::0014
reverse: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' previous AAAA record, now has a reverse record, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
aaaa_rec: fd00::0014
reverse: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' has PTR record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ zone_prefix_reverse_24 }}"
name: "124"
ptr_hostname: "host04.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' has PTR record, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ zone_prefix_reverse_24 }}"
name: "124"
ptr_hostname: "host04.{{ testzone }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' has PTR record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ zone_prefix_reverse_24 }}"
name: "124"
ptr_rec: "host04.{{ testzone }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' has PTR record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ zone_prefix_reverse_24 }}"
name: "124"
ptr_rec: "host04.{{ testzone }}"
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' has DNAME record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
dname_target: "ipa.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' has DNAME record, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
dname_target: "ipa.{{ testzone }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' DNAME record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
dname_rec: "ipa.{{ testzone }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' DNAME record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
dname_rec: "ipa.{{ testzone }}"
state: absent
register: result
failed_when: result.changed or result.failed
# This task only ensures proper records are present,
# it is not testing anything, and should not faild.
- name: Ensure that 'host04' has a A record with reverse, for NS record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
ip_address: "{{ ipv4_prefix }}.114"
reverse: yes
register: result
failed_when: result.failed
- name: Ensure that 'host04' has NS record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
ns_hostname: host04
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' has NS record, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
ns_hostname: host04
register: result
# IPA issue 8850 should be fixed before we handle the failed_when
# message. For now, we'll just test if it does not fail.
failed_when: result.changed or not result.failed
- name: Ensure that 'host04' NS record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
ns_rec: host04
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' NS record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
ns_rec: host04
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' DLV record is present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
dlv_key_tag: 12345
dlv_algorithm: 3
dlv_digest_type: 1
# digest is sha1sum of 'host04."{{ testzone }}"'
dlv_digest: 08ff468cb25ccd21642989294cc33570da5eb2ba
register: result
failed_when: result.failed or not result.changed
- name: Ensure that 'host04' DLV record is present, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
dlv_key_tag: 12345
dlv_algorithm: 3
dlv_digest_type: 1
dlv_digest: 08ff468cb25ccd21642989294cc33570da5eb2ba
register: result
failed_when: result.failed or result.changed
- name: Ensure that 'host04' DLV record is present, with a different key tag.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
dlv_key_tag: 4321
dlv_record: 12345 3 1 08ff468cb25ccd21642989294cc33570da5eb2ba
register: result
failed_when: result.failed or not result.changed
- name: Ensure that 'host04' DLV second record is present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
dlv_key_tag: 4321
dlv_algorithm: 2
dlv_digest_type: 2
# digest is sha1sum of 'second record'
dlv_digest: da39a3ee5e6b4b0d3255bfef95601890afd80709
register: result
failed_when: result.failed or not result.changed
- name: Ensure that 'host04' DLV record is changed, in presence of multiple records.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
dlv_key_tag: 54321
dlv_record: 4321 3 1 08ff468cb25ccd21642989294cc33570da5eb2ba
register: result
failed_when: result.failed or not result.changed
- name: Ensure that 'host04' DLV record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
dlv_record: 54321 3 1 08ff468cb25ccd21642989294cc33570da5eb2ba
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure that 'host04' DLV record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
dlv_record: 54321 3 1 08ff468cb25ccd21642989294cc33570da5eb2ba
state: absent
register: result
failed_when: result.failed or result.changed
- name: Ensure that 'host04' DLV record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
dlv_record: 4321 2 2 da39a3ee5e6b4b0d3255bfef95601890afd80709
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure that dns record 'iron01' is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: iron01
zone_name: "{{ safezone }}"
ip_address: "{{ ansible_facts['default_ipv4'].address }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that NS record for "{{ safezone }}" is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: iron01
zone_name: "{{ safezone }}"
ns_hostname: iron01
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'iron01' DS record is present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ safezone }}"
name: iron01
ds_key_tag: 12345
ds_algorithm: 3
ds_digest_type: 1
# digest is sha1sum of 'iron01."{{ safezone }}"'
ds_digest: 84763786e4213cca9a6938dba5dacd64f87ec216
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'iron01' DS record is present, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ safezone }}"
name: iron01
ds_key_tag: 12345
ds_algorithm: 3
ds_digest_type: 1
ds_digest: 84763786e4213cca9a6938dba5dacd64f87ec216
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'iron01' DS record is present, with a different key tag.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ safezone }}"
name: iron01
ds_key_tag: 54321
ds_rec: 12345 3 1 84763786e4213cca9a6938dba5dacd64f87ec216
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'iron01' DS record is present, with a different key tag, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ safezone }}"
name: iron01
ds_key_tag: 54321
ds_rec: 12345 3 1 84763786e4213cca9a6938dba5dacd64f87ec216
register: result
failed_when: result.changed or (result.failed and "DS record does not contain" not in result.msg)
- name: Ensure that 'iron01' DS record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ safezone }}"
name: iron01
ds_rec: 54321 3 1 84763786e4213cca9a6938dba5dacd64f87ec216
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'iron01' DS record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ safezone }}"
name: iron01
ds_rec: 54321 3 1 84763786e4213cca9a6938dba5dacd64f87ec216
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' AFSDB record is present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
afsdb_subtype: 1
afsdb_hostname: "host04.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' AFSDB record is present, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
afsdb_subtype: 1
afsdb_hostname: "host04.{{ testzone }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' AFSDB record subtype is 2.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
afsdb_subtype: 2
afsdb_rec: "1 host04.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' AFSDB record subtype is 2, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
afsdb_subtype: 2
afsdb_rec: "1 host04.{{ testzone }}"
register: result
failed_when: result.changed or (result.failed and "AFSDB record does not contain" not in result.msg)
- name: Ensure that 'host04' AFSDB record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
afsdb_rec: "2 host04.{{ testzone }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' AFSDB record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
afsdb_rec: "2 host04.{{ testzone }}"
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' CERT record is present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
cert_type: 1
cert_key_tag: 1234
cert_algorithm: 3
cert_certificate_or_crl: "{{ lookup('file', 'cert1.b64') }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' CERT record is present, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
cert_type: 1
cert_key_tag: 1234
cert_algorithm: 3
cert_certificate_or_crl: "{{ lookup('file', 'cert1.b64') }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' CERT record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
cert_rec: "1 1234 3 {{ lookup('file', 'cert1.b64') }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' CERT record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
cert_rec: 1 1234 3 "{{ lookup('file', 'cert1.b64') }}"
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' KX record is present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
kx_preference: 10
kx_exchanger: "keyex.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' KX record is present, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
kx_preference: 10
kx_exchanger: "keyex.{{ testzone }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' KX record is present with preference set to 20.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
kx_preference: 20
kx_rec: "10 keyex.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' KX record is present with preference set to 20, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
kx_preference: 20
kx_rec: "10 keyex.{{ testzone }}"
register: result
failed_when: result.changed or (result.failed and "KX record does not contain" not in result.msg)
- name: Ensure that 'host04' KX record is present with preference set to 20, one more time.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
kx_preference: 20
kx_rec: "20 keyex.{{ testzone }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' KX record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
kx_rec: "20 keyex.{{ testzone }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' KX record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
kx_rec: "20 keyex.{{ testzone }}"
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' MX record is present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
mx_preference: 10
mx_exchanger: "mail.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' MX record is present, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
mx_preference: 10
mx_exchanger: "mail.{{ testzone }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' MX record is present with preference set to 20.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
mx_preference: 20
mx_rec: "10 mail.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' MX record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
mx_rec: "20 mail.{{ testzone }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' MX record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
mx_rec: "20 mail.{{ testzone }}"
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' LOC record is present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
loc_lat_deg: 52
loc_lat_min: 22
loc_lat_sec: 23.000
loc_lat_dir: N
loc_lon_deg: 4
loc_lon_min: 53
loc_lon_sec: 32.00
loc_lon_dir: E
loc_altitude: -2.00
loc_size: 0.00
loc_h_precision: 10000
loc_v_precision: 10
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' LOC record is present, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
loc_lat_deg: 52
loc_lat_min: 22
loc_lat_sec: 23.000
loc_lat_dir: N
loc_lon_deg: 4
loc_lon_min: 53
loc_lon_sec: 32.000
loc_lon_dir: E
loc_altitude: -2.00
loc_size: 0.00
loc_h_precision: 10000
loc_v_precision: 10
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' LOC record is present, with loc_size 1.00.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
loc_size: 1.00
loc_rec: 52 22 23.000 N 4 53 32.000 E -2.00 0.00 10000.00 10.00
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' LOC record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
loc_rec: 52 22 23.000 N 4 53 32.000 E -2.00 1.00 10000.00 10.00
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' LOC record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
loc_rec: 52 22 23.000 N 4 53 32.000 E -2.00 1.00 10000.00 10.00
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that '_sip._udp' service has NAPTR record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
naptr_order: 100
naptr_preference: 10
naptr_flags: "U"
naptr_service: "SIP+D2U"
naptr_regexp: "!^.*$!sip:info@example.com!"
naptr_replacement: "."
register: result
failed_when: result.failed or not result.changed or result.failed
- name: Ensure that '_sip._udp' service has NAPTR record, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
naptr_order: 100
naptr_preference: 10
naptr_flags: "U"
naptr_service: "SIP+D2U"
naptr_regexp: "!^.*$!sip:info@example.com!"
naptr_replacement: "."
register: result
failed_when: result.failed or result.changed
- name: Change '_sip._udp' service NAPTR record `preference` to 20.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
naptr_preference: 20
naptr_rec: '100 10 U SIP+D2U !^.*$!sip:info@example.com! .'
register: result
failed_when: result.failed or not result.changed
- name: Ensure that '_sip._udp' service has NAPTR record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
naptr_order: 101
naptr_preference: 11
naptr_flags: "U"
naptr_service: "SIP+D2U"
naptr_regexp: "!^.*$!sip:debug@example.com!"
naptr_replacement: "."
- name: Ensure that '_sip._udp' service has NAPTR record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
naptr_order: 102
naptr_preference: 12
naptr_flags: "U"
naptr_service: "SIP+D2U"
naptr_regexp: "!^.*$!sip:prio@example.com!"
naptr_replacement: "."
- name: Change '_sip._udp' service NAPTR record `preference` to 50, when multiple records are present. (BZ 1881436)
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
naptr_preference: 50
naptr_rec: '100 20 U SIP+D2U !^.*$!sip:info@example.com! .'
register: result
failed_when: result.failed or not result.changed
- name: Ensure that '_sip._udp' service has NAPTR record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
record_type: NAPTR
record_value: '100 50 U SIP+D2U !^.*$!sip:info@example.com! .'
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure that '_sip._udp' service has NAPTR record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
record_type: NAPTR
record_value: '100 50 U SIP+D2U !^.*$!sip:info@example.com! .'
state: absent
register: result
failed_when: result.failed or result.changed
- name: Clear NAPTR records.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
del_all: yes
state: absent
- name: Ensure that '_sip._udp' service has SRV record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
srv_priority: 10
srv_weight: 10
srv_port: 5060
srv_target: "sip-server.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure that '_sip._udp' service has SRV record, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
srv_priority: 10
srv_weight: 10
srv_port: 5060
srv_target: "sip-server.{{ testzone }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure '_sip._udp' SRV record has priority equals to 4.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
srv_priority: 4
srv_weight: 10
srv_port: 5060
srv_target: "sip-server.{{ testzone }}"
srv_rec: "10 10 5060 sip-server.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure '_sip._udp' SRV record has priority equals to 4, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
srv_priority: 4
srv_weight: 10
srv_port: 5060
srv_target: sip-server."{{ testzone }}"
srv_rec: "10 10 5060 sip-server.{{ testzone }}"
register: result
failed_when: result.changed or (result.failed and "SRV record does not contain" not in result.msg)
- name: Ensurer '_sip._udp' SRV record has priority 2, weight 20
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
srv_priority: 2
srv_weight: 20
srv_port: 5060
srv_target: "sip-server.{{ testzone }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensurer '_sip._udp' SRV record has priority 2, weight 20, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
srv_priority: 2
srv_weight: 20
srv_port: 5060
srv_target: "sip-server.{{ testzone }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure that '_sip._udp' SRV record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
srv_record: "2 20 5060 sip-server.{{ testzone }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that '_sip._udp' SRV record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _sip._udp
srv_record: "2 20 5060 sip-server.{{ testzone }}"
state: absent
register: result
failed_when: result.changed or result.failed
# SSHFP fingerprint generated with `ssh-keygen -r host04."{{ testzone }}"`
- name: Ensure that 'host04' has SSHFP record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
sshfp_algorithm: 1
sshfp_fp_type: 1
sshfp_fingerprint: d21802c61733e055b8d16296cbce300efb8a167a
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' has SSHFP record, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
sshfp_algorithm: 1
sshfp_fp_type: 1
sshfp_fingerprint: d21802c61733e055b8d16296cbce300efb8a167a
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' SSHFP record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
sshfp_rec: 1 1 d21802c61733e055b8d16296cbce300efb8a167a
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' SSHFP record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
sshfp_rec: 1 1 d21802c61733e055b8d16296cbce300efb8a167a
state: absent
register: result
failed_when: result.changed or result.failed
# Data is sha356sum of 'Some Text to Test', it should be created from
# a real certificate.
- name: Ensure that 'host04' has TLSA record present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
tlsa_cert_usage: 3
tlsa_selector: 1
tlsa_matching_type: 1
tlsa_cert_association_data: 9c0ad776dbeae8d9d55b0ad42899d30235c114d5f918fd69746e4279e47bdaa2
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' has TLSA record present, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
tlsa_cert_usage: 3
tlsa_selector: 1
tlsa_matching_type: 1
tlsa_cert_association_data: 9c0ad776dbeae8d9d55b0ad42899d30235c114d5f918fd69746e4279e47bdaa2
register: result
failed_when: result.changed or result.failed
- name: Modify 'host04' has TLSA record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
tlsa_matching_type: 0
tlsa_rec: 3 1 1 9c0ad776dbeae8d9d55b0ad42899d30235c114d5f918fd69746e4279e47bdaa2
register: result
failed_when: not result.changed or result.failed
- name: Modify 'host04' has TLSA record, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
tlsa_matching_type: 0
tlsa_rec: 3 1 1 9c0ad776dbeae8d9d55b0ad42899d30235c114d5f918fd69746e4279e47bdaa2
register: result
failed_when: result.changed or (result.failed and "TLSA record does not contain" not in result.msg)
- name: Ensure that 'host04' TLSA record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
tlsa_rec: 3 1 0 9c0ad776dbeae8d9d55b0ad42899d30235c114d5f918fd69746e4279e47bdaa2
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' TLSA record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
tlsa_rec: 3 1 0 9c0ad776dbeae8d9d55b0ad42899d30235c114d5f918fd69746e4279e47bdaa2
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' has TXT record present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
txt_data: Some Text
register: result
failed_when: not result.changed or result.failed
# - name: Ensure that 'host04' has TXT record present, again.
# ipadnsrecord:
# ipaadmin_password: SomeADMINpassword
# ipaapi_context: "{{ ipa_context | default(omit) }}"
# zone_name: "{{ testzone }}"
# name: host04
# txt_data: Some Text
# register: result
# failed_when: result.changed or result.failed
- name: Change value of 'host04' TXT record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
txt_data: Some new Text
txt_rec: Some Text
register: result
failed_when: not result.changed or result.failed
- name: Add a second TXT record to 'host04'.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
txt_rec: Some Other Text
register: result
failed_when: not result.changed or result.failed
- name: Add a second TXT record to 'host04', again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
txt_rec: Some Other Text
register: result
failed_when: result.changed or result.failed
- name: Ensure that one of 'host04' TXT record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
txt_rec: Some new Text
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that one of 'host04' TXT record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
txt_rec: Some new Text
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that 'host04' TXT record are all absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
txt_rec:
- Some new Text
- Some Other Text
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that 'host04' TXT record are all absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: host04
txt_rec:
- Some new Text
- Some Other Text
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure that '_ftp._tcp' has URI record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _ftp._tcp
uri_priority: 10
uri_weight: 1
uri_target: ftp://ftp.host04.{{ testzone }}/public
register: result
failed_when: not result.changed or result.failed
- name: Ensure that '_ftp._tcp' has URI record, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _ftp._tcp
uri_priority: 10
uri_weight: 1
uri_target: ftp://ftp.host04.{{ testzone }}/public
register: result
failed_when: result.changed or result.failed
- name: Change '_ftp._tcp' URI record weight to 3 and priority to 5.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _ftp._tcp
uri_priority: 5
uri_weight: 3
uri_rec: 10 1 "ftp://ftp.host04.{{ testzone }}/public"
register: result
failed_when: not result.changed or result.failed
- name: Verify if modification worked.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _ftp._tcp
uri_rec: 10 1 ftp://ftp.host04.{{ testzone }}/public
state: absent
register: result
failed_when: result.changed or result.failed
- name: Change '_ftp._tcp' URI record weight to 3 and priority to 5, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _ftp._tcp
uri_priority: 5
uri_weight: 3
uri_rec: 5 3 "ftp://ftp.host04.{{ testzone }}/public"
register: result
failed_when: result.changed or result.failed
- name: Ensure that '_ftp._tcp' URI record is absent.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _ftp._tcp
uri_rec: 5 3 "ftp://ftp.host04.{{ testzone }}/public"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that '_ftp._tcp' URI record is absent, again.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ testzone }}"
name: _ftp._tcp
uri_rec: 5 3 "ftp://ftp.host04.{{ testzone }}/public"
state: absent
register: result
failed_when: result.changed or result.failed
# cleanup
- name: Cleanup test environment.
ansible.builtin.include_tasks: env_cleanup.yml
- name: Remove certificate files.
ansible.builtin.shell: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/dnsrecord/test_dnsrecord_client_context.yml 0000664 0000000 0000000 00000002435 14600563364 0027404 0 ustar 00root root 0000000 0000000 ---
- name: Test dnsrecord
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test dnsrecord using client context, in client host.
ansible.builtin.import_playbook: test_dnsrecord.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test dnsrecord using client context, in server host.
ansible.builtin.import_playbook: test_dnsrecord.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/dnsrecord/test_dnsrecord_full_records.yml 0000664 0000000 0000000 00000007776 14600563364 0027062 0 ustar 00root root 0000000 0000000 ---
- name: Test dnsrecord with full records (*-rec variables).
hosts: ipaserver
become: yes
gather_facts: yes
tasks:
- name: Setup test environment
ansible.builtin.include_tasks: env_setup.yml
# tests
- name: Ensure that dns A record for 'host01' is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: "{{ testzone }}"
a_rec: 192.168.122.101
register: result
failed_when: not result.changed or result.failed
- name: Ensure that dns A record for 'host01' is present, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: "{{ testzone }}"
a_rec: 192.168.122.101
register: result
failed_when: result.changed or result.failed
- name: Ensure that dns A records for 'host01' are present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: "{{ testzone }}"
a_rec:
- 192.168.122.101
- 192.168.122.102
- 192.168.122.103
register: result
failed_when: not result.changed or result.failed
- name: Ensure that dns A records for 'host01' are present, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: "{{ testzone }}"
a_rec:
- 192.168.122.101
- 192.168.122.102
- 192.168.122.103
register: result
failed_when: result.changed or result.failed
- name: Ensure that dns A records for 'host01' are absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: "{{ testzone }}"
a_rec:
- 192.168.122.101
- 192.168.122.102
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that dns A records for 'host01' are absent, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: "{{ testzone }}"
a_rec:
- 192.168.122.101
- 192.168.122.102
state: absent
register: result
failed_when: result.changed or result.failed
####
- name: Ensure that dns AAAA record for 'host01' is present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: "{{ testzone }}"
aaaa_rec: fd00::0001
register: result
failed_when: not result.changed or result.failed
- name: Ensure that dns AAAA record for 'host01' is present, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: "{{ testzone }}"
aaaa_rec: fd00::0001
register: result
failed_when: result.changed or result.failed
- name: Ensure that dns AAAA records for 'host01' are present
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: "{{ testzone }}"
aaaa_rec:
- fd00::0001
- fd00::0011
- fd00::0021
register: result
failed_when: not result.changed or result.failed
- name: Ensure that dns AAAAA records for 'host01' are present, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: "{{ testzone }}"
aaaa_rec:
- fd00::0001
- fd00::0011
- fd00::0021
register: result
failed_when: result.changed or result.failed
- name: Ensure that dns AAAAA records for 'host01' are absent
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: "{{ testzone }}"
aaaa_rec:
- fd00::0001
- fd00::0011
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure that dns AAAAA records for 'host01' are absent, again
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
name: host01
zone_name: "{{ testzone }}"
aaaa_rec:
- fd00::0001
- fd00::0011
state: absent
register: result
failed_when: result.changed or result.failed
# Cleanup
- name: Cleanup test environment.
ansible.builtin.include_tasks: env_cleanup.yml
ansible-freeipa-master/tests/dnsrecord/test_dnsrecord_modify_record.yml 0000664 0000000 0000000 00000012703 14600563364 0027206 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure
hosts: ipaserver
become: no
gather_facts: yes
tasks:
- name: Setup testing environment.
ansible.builtin.include_tasks: env_setup.yml
- name: Add test host.
ipahost:
ipaadmin_password: SomeADMINpassword
name: "iron01.{{ safezone }}"
ip_address: 192.168.1.253
force: yes
- name: Cleanup test records.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
records:
- name: iron01
ns_rec: iron01
ds_record:
- 1234 3 3 84763786e4213cca9a6938dba5dacd64f87ec216
- 1234 3 3 84763786e4213cca9a6938dba5dacd64f87ec222
- 5555 5 5 84763786e4213cca9a6938dba5dacd64f87ec222
cert_record:
- 1 1234 3 AwIBAgIUb14+Oug2nPMIIBdTCCAR+g
- 2 567 4 AwIBAgIUb14+Oug2nPMIIBdTCCAR+g
state: absent
- name: Add NS records to test.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
records:
- name: iron01
ns_rec: iron01
register: result
failed_when: result.failed or not result.changed
- name: Add DS records to test.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
records:
- name: iron01
ds_record:
- 1234 3 3 84763786e4213cca9a6938dba5dacd64f87ec216
- 1234 3 3 84763786e4213cca9a6938dba5dacd64f87ec222
register: result
failed_when: result.failed or not result.changed
- name: Add CERT records to test.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
records:
- name: host01
cert_record:
- 1 1234 3 AwIBAgIUb14+Oug2nPMIIBdTCCAR+g
- 5 555 4 AwIBAgIUb14+Oug2nPMIIBdTCCAAS+g
register: result
failed_when: result.failed or not result.changed
- name: Modify CERT record.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
name: host01
cert_type: 2
cert_key_tag: 567
cert_algorithm: 4
cert_rec: 1 1234 3 AwIBAgIUb14+Oug2nPMIIBdTCCAR+g
register: result
failed_when: result.failed or not result.changed
- name: Verify modified CERT records exists.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
records:
- name: host01
cert_record: 2 567 4 AwIBAgIUb14+Oug2nPMIIBdTCCAR+g
register: result
failed_when: result.failed or result.changed
- name: Verify if old CERT record does not exist.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
records:
- name: host01
cert_record: 1 1234 3 AwIBAgIUb14+Oug2nPMIIBdTCCAR+g
state: absent
register: result
failed_when: result.failed or result.changed
- name: Verify if unmodified CERT record does exist.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
records:
- name: host01
cert_record: 5 555 4 AwIBAgIUb14+Oug2nPMIIBdTCCAAS+g
register: result
failed_when: result.failed or result.changed
- name: Try to modify the same DS record twice.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
records:
- name: iron01
ds_key_tag: 5555
ds_algorithm: 5
ds_digest_type: 5
ds_digest: 84763786e4213cca9a6938dba5dacd64f87ec222
ds_record: 1234 3 3 84763786e4213cca9a6938dba5dacd64f87ec216
- name: iron01
ds_key_tag: 5555
ds_algorithm: 5
ds_digest_type: 5
ds_digest: 84763786e4213cca9a6938dba5dacd64f87ec222
ds_record: 1234 3 3 84763786e4213cca9a6938dba5dacd64f87ec216
register: result
failed_when: not result.failed or "DS record does not contain" not in result.msg
- name: Verify if unmodified DS record still exists.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
records:
- name: iron01
ds_record: 1234 3 3 84763786e4213cca9a6938dba5dacd64f87ec222
register: result
failed_when: result.failed or result.changed
- name: Verify DS record was modified
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
records:
- name: iron01
ds_record: 5555 5 5 84763786e4213cca9a6938dba5dacd64f87ec222
register: result
failed_when: result.failed or result.changed
- name: Verify if modified DS record was not created.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
records:
- name: iron01
ds_record: 1234 3 3 84763786e4213cca9a6938dba5dacd64f87ec216
state: absent
register: result
failed_when: result.failed or result.changed
- name: Cleanup test records.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
zone_name: safezone.test
records:
- name: iron01
ds_record:
- 1234 3 3 84763786e4213cca9a6938dba5dacd64f87ec216
- 1234 3 3 84763786e4213cca9a6938dba5dacd64f87ec222
- 5555 5 5 84763786e4213cca9a6938dba5dacd64f87ec222
- name: host01
cert_record:
- 1 1234 3 AwIBAgIUb14+Oug2nPMIIBdTCCAR+g
- 2 567 4 AwIBAgIUb14+Oug2nPMIIBdTCCAR+g
state: absent
# cleanup
- name: Cleanup test environment.
ansible.builtin.include_tasks: env_cleanup.yml
ansible-freeipa-master/tests/dnszone/ 0000775 0000000 0000000 00000000000 14600563364 0020226 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/dnszone/env_cleanup.yml 0000664 0000000 0000000 00000000636 14600563364 0023255 0 ustar 00root root 0000000 0000000 ---
- name: Ensure zone is absent.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- testzone.local
- test1.testzone.local
- test2.testzone.local
- test3.testzone.local
- 2.0.192.in-addr.arpa.
- 0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.f.ip6.arpa.
- 1.0.0.0.e.f.a.c.8.b.d.0.1.0.0.2.ip6.arpa.
state: absent
ansible-freeipa-master/tests/dnszone/env_setup.yml 0000664 0000000 0000000 00000000127 14600563364 0022761 0 ustar 00root root 0000000 0000000 ---
- name: Cleanup test environment.
ansible.builtin.include_tasks: env_cleanup.yml
ansible-freeipa-master/tests/dnszone/env_teardown.yml 0000664 0000000 0000000 00000000127 14600563364 0023444 0 ustar 00root root 0000000 0000000 ---
- name: Cleanup test environment.
ansible.builtin.include_tasks: env_cleanup.yml
ansible-freeipa-master/tests/dnszone/test_dnszone.yml 0000664 0000000 0000000 00000014674 14600563364 0023504 0 ustar 00root root 0000000 0000000 ---
- name: Test dnszone
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: true
module_defaults:
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
tasks:
# Setup
- name: Setup testing environment
ansible.builtin.include_tasks: env_setup.yml
# Tests
- name: Check if zone is present, when it shouldn't be.
ipadnszone:
name: testzone.local
state: present
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Check if zone is present again, when it shouldn't be.
ipadnszone:
name: testzone.local
state: present
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure zone is present.
ipadnszone:
name: testzone.local
state: present
register: result
failed_when: not result.changed or result.failed
- name: Check if zone is present, when it should be.
ipadnszone:
name: testzone.local
state: present
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure zone is present, again.
ipadnszone:
name: testzone.local
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure zone is disabled.
ipadnszone:
name: testzone.local
state: disabled
register: result
failed_when: not result.changed or result.failed
- name: Ensure zone is disabled, again.
ipadnszone:
name: testzone.local
state: disabled
register: result
failed_when: result.changed or result.failed
- name: Ensure zone is enabled.
ipadnszone:
name: testzone.local
state: enabled
register: result
failed_when: not result.changed or result.failed
- name: Ensure zone is enabled, again.
ipadnszone:
name: testzone.local
state: enabled
register: result
failed_when: result.changed or result.failed
- name: Ensure forward_policy is none.
ipadnszone:
name: testzone.local
forward_policy: none
register: result
failed_when: not result.changed or result.failed
- name: Ensure forward_policy is none, again.
ipadnszone:
name: testzone.local
forward_policy: none
register: result
failed_when: result.changed or result.failed
- name: Ensure forward_policy is first.
ipadnszone:
name: testzone.local
forward_policy: first
register: result
failed_when: not result.changed or result.failed
- name: Ensure forward_policy is first, again.
ipadnszone:
name: testzone.local
forward_policy: first
register: result
failed_when: result.changed or result.failed
- name: Ensure first forwarder is set.
ipadnszone:
name: testzone.local
forwarders:
- ip_address: 8.8.8.8
port: 53
register: result
failed_when: not result.changed or result.failed
- name: Ensure first and second forwarder are set.
ipadnszone:
name: testzone.local
forwarders:
- ip_address: 8.8.8.8
port: 53
- ip_address: 2001:4860:4860::8888
register: result
failed_when: not result.changed or result.failed
- name: Ensure first and second forwarder are set, again.
ipadnszone:
name: testzone.local
forwarders:
- ip_address: 8.8.8.8
port: 53
- ip_address: 2001:4860:4860::8888
register: result
failed_when: result.changed or result.failed
- name: Ensure only second forwarder is set.
ipadnszone:
name: testzone.local
forwarders:
- ip_address: 2001:4860:4860::8888
register: result
failed_when: not result.changed or result.failed
- name: Nothing changes.
ipadnszone:
name: testzone.local
register: result
failed_when: result.changed or result.failed
- name: Ensure no forwarders are set.
ipadnszone:
name: testzone.local
forwarders: []
register: result
failed_when: not result.changed or result.failed
- name: Create zones test1
ipadnszone:
name: test1.testzone.local
register: result
failed_when: not result.changed or result.failed
- name: Create zones test1, again
ipadnszone:
name: test1.testzone.local
register: result
failed_when: result.changed or result.failed
- name: Create zones test2
ipadnszone:
name: test2.testzone.local
register: result
failed_when: not result.changed or result.failed
- name: Create zones test2, again
ipadnszone:
name: test2.testzone.local
register: result
failed_when: result.changed or result.failed
- name: Create zones test3
ipadnszone:
name: test3.testzone.local
register: result
failed_when: not result.changed or result.failed
- name: Create zones test3, again
ipadnszone:
name: test3.testzone.local
register: result
failed_when: result.changed or result.failed
- name: Ensure zone test1.testzone.local has management permissioon
ipadnszone:
name: test1.testzone.local
permission: true
register: result
failed_when: not result.changed or result.failed
- name: Ensure zone test1.testzone.local has management permissioon
ipadnszone:
name: test1.testzone.local
permission: true
register: result
failed_when: result.changed or result.failed
- name: Ensure zone test1.testzone.local don't have management permissioon
ipadnszone:
name: test1.testzone.local
permission: false
register: result
failed_when: not result.changed or result.failed
- name: Ensure zone test1.testzone.local don't have management permissioon
ipadnszone:
name: test1.testzone.local
permission: false
register: result
failed_when: result.changed or result.failed
- name: Ensure multiple zones are absent
ipadnszone:
name:
- test1.testzone.local
- test2.testzone.local
- test3.testzone.local
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure multiple zones are absent, again
ipadnszone:
name:
- test1.testzone.local
- test2.testzone.local
- test3.testzone.local
state: absent
register: result
failed_when: result.changed or result.failed
# Teardown
- name: Teardown testing environment
ansible.builtin.include_tasks: env_teardown.yml
ansible-freeipa-master/tests/dnszone/test_dnszone_client_context.yml 0000664 0000000 0000000 00000002421 14600563364 0026571 0 ustar 00root root 0000000 0000000 ---
- name: Test dnszone
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test dnszone using client context, in client host.
ansible.builtin.import_playbook: test_dnszone.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test dnszone using client context, in server host.
ansible.builtin.import_playbook: test_dnszone.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/dnszone/test_dnszone_mod.yml 0000664 0000000 0000000 00000017076 14600563364 0024342 0 ustar 00root root 0000000 0000000 ---
- name: Test dnszone
hosts: ipaserver
become: true
gather_facts: true
tasks:
# Setup
- name: Setup testing environment
ansible.builtin.include_tasks: env_setup.yml
- name: Ensure zone is present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_sync_ptr: true
dynamic_update: true
dnssec: true
allow_transfer:
- 1.1.1.1
- 2.2.2.2
allow_query:
- 1.1.1.1
- 2.2.2.2
refresh: 3600
retry: 900
expire: 1209600
minimum: 3600
ttl: 60
default_ttl: 60
name_server: ipaserver.test.local.
skip_nameserver_check: true
admin_email: admin@example.com
nsec3param_rec: "1 7 100 abcd"
state: present
register: result
failed_when: not result.changed or result.failed
- name: Set different nsec3param_rec.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
nsec3param_rec: "2 8 200 abcd"
register: result
failed_when: not result.changed or result.failed
- name: Set same nsec3param_rec.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
nsec3param_rec: "2 8 200 abcd"
register: result
failed_when: result.changed or result.failed
- name: Set default_ttl to 1200
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
default_ttl: 1200
register: result
failed_when: not result.changed or result.failed
- name: Set default_ttl to 1200, again
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
default_ttl: 1200
register: result
failed_when: result.changed or result.failed
- name: Set ttl to 900
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
ttl: 900
register: result
failed_when: not result.changed or result.failed
- name: Set ttl to 900, again
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
ttl: 900
register: result
failed_when: result.changed or result.failed
- name: Set minimum to 1000
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
minimum: 1000
register: result
failed_when: not result.changed or result.failed
- name: Set minimum to 1000, again
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
minimum: 1000
register: result
failed_when: result.changed or result.failed
- name: Set expire to 1209601
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
expire: 1209601
register: result
failed_when: not result.changed or result.failed
- name: Set expire to 1209601, again
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
expire: 1209601
register: result
failed_when: result.changed or result.failed
- name: Set retry to 1200.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
retry: 1200
register: result
failed_when: not result.changed or result.failed
- name: Set retry to 1200, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
retry: 1200
register: result
failed_when: result.changed or result.failed
- name: Set refresh to 4000.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
refresh: 4000
register: result
failed_when: not result.changed or result.failed
- name: Set refresh to 4000, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
refresh: 4000
register: result
failed_when: result.changed or result.failed
- name: Set dnssec to false.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
dnssec: false
register: result
failed_when: not result.changed or result.failed
- name: Set dnssec to false, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
dnssec: false
register: result
failed_when: result.changed or result.failed
- name: Set allow_sync_ptr to false.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_sync_ptr: false
register: result
failed_when: not result.changed or result.failed
- name: Set allow_sync_ptr to false, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_sync_ptr: false
register: result
failed_when: result.changed or result.failed
- name: Set dynamic_update to false.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
dynamic_update: false
register: result
failed_when: not result.changed or result.failed
- name: Set dynamic_update to false, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
dynamic_update: false
register: result
failed_when: result.changed or result.failed
- name: Update allow_transfer.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_transfer:
- 1.1.1.1
- 2.2.2.2
- 3.3.3.3
register: result
failed_when: not result.changed or result.failed
- name: Update allow_transfer, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_transfer:
- 1.1.1.1
- 2.2.2.2
- 3.3.3.3
register: result
failed_when: result.changed or result.failed
- name: Remove allow transfer.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_transfer: []
register: result
failed_when: not result.changed or result.failed
- name: Remove allow transfer, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_transfer: []
register: result
failed_when: result.changed or result.failed
- name: Update allow_query.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_query:
- 1.1.1.1
- 2.2.2.2
- 3.3.3.3
register: result
failed_when: not result.changed or result.failed
- name: Update allow_query, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_query:
- 1.1.1.1
- 2.2.2.2
- 3.3.3.3
register: result
failed_when: result.changed or result.failed
- name: Ensure allow query is empty.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_query: []
register: result
failed_when: not result.changed or result.failed
- name: Ensure allow query is empty, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
allow_query: []
register: result
failed_when: result.changed or result.failed
- name: Update admin email.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
admin_email: admin2@example.com
register: result
failed_when: not result.changed or result.failed
- name: Update admin email, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: testzone.local
admin_email: admin2@example.com
register: result
failed_when: result.changed or result.failed
# Teardown
- name: Teardown testing environment
ansible.builtin.include_tasks: env_teardown.yml
ansible-freeipa-master/tests/dnszone/test_dnszone_name_from_ip.yml 0000664 0000000 0000000 00000005545 14600563364 0026214 0 ustar 00root root 0000000 0000000 ---
- name: Test dnszone
hosts: ipaserver
become: yes
gather_facts: yes
tasks:
# Setup
- name: Setup testing environment
ansible.builtin.include_tasks: env_setup.yml
# Tests
- name: Ensure zone exists for reverse IP.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 192.0.2.3/24
register: ipv4_zone
failed_when: not ipv4_zone.changed or ipv4_zone.failed
- name: Ensure zone exists for reverse IP, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 192.0.2.3/24
register: result
failed_when: result.changed or result.failed
- name: Ensure zone exists for reverse IP, given the zone name.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: "{{ ipv4_zone.dnszone.name }}"
register: result
failed_when: result.changed or result.failed
- name: Modify existing zone, using `name_from_ip`.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 192.0.2.3/24
default_ttl: 1234
register: result
failed_when: not result.changed or result.failed
- name: Modify existing zone, using `name_from_ip`, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 192.0.2.3/24
default_ttl: 1234
register: result
failed_when: result.changed or result.failed
- name: Ensure ipv6 zone exists for reverse IPv6.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: fd00::0001
register: ipv6_zone
failed_when: not ipv6_zone.changed or ipv6_zone.failed
# - ansible.builtin.debug:
# msg: "{{ipv6_zone}}"
- name: Ensure ipv6 zone was created.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: "{{ ipv6_zone.dnszone.name }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure ipv6 zone exists for reverse IPv6, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: fd00::0001
register: result
failed_when: result.changed or result.failed
- name: Ensure second ipv6 zone exists for reverse IPv6.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 2001:db8:cafe:1::1
register: ipv6_sec_zone
failed_when: not ipv6_sec_zone.changed or ipv6_zone.failed or ipv6_sec_zone.failed
- name: Ensure second ipv6 zone was created.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: "{{ ipv6_sec_zone.dnszone.name }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure second ipv6 zone exists for reverse IPv6, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 2001:db8:cafe:1::1
register: result
failed_when: result.changed or result.failed
# Teardown
- name: Teardown testing environment
ansible.builtin.include_tasks: env_teardown.yml
ansible-freeipa-master/tests/env_freeipa_facts.yml 0000664 0000000 0000000 00000003034 14600563364 0022734 0 ustar 00root root 0000000 0000000 # This playbook should be included with `include_tasks` as the first task
# of a test playbook that requires FreeIPA information.
#
# Available Facts:
#
# ipa_version: The installed FreeIPA version.
# ipa_api_version: The installed FreeIPA API version.
#
---
- name: Retrieving FreeIPA version.
ansible.builtin.shell:
cmd: 'ipa --version | sed -n "s/VERSION: \([^,]*\).*API_VERSION: \([^,]*\).*/\1\\n\2/p"'
register: ipa_cmd_version
- name: Verify if host is an IPA server or client.
ansible.builtin.shell:
cmd: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
RESULT=$(KRB5CCNAME={{ krb5ccname }} ipa server-show `hostname` && echo SERVER || echo CLIENT)
kdestroy -A -c {{ krb5ccname }}
echo $RESULT
vars:
krb5ccname: "__check_ipa_host_is_client_or_server__"
register: output
- name: Set FreeIPA facts.
ansible.builtin.set_fact:
ipa_version: "{{ ipa_cmd_version.stdout_lines[0] }}"
ipa_api_version: "{{ ipa_cmd_version.stdout_lines[1] }}"
ipa_host_is_client: "{{ (output.stdout_lines[-1] == 'CLIENT') | bool }}"
trust_test_is_supported: no
- name: Ensure ipaserver_domain is set
when: ipaserver_domain is not defined
block:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: "'fqdn' in ansible_facts"
- name: Set Domain to 'ipa.test' if FQDN could not be retrieved.
ansible.builtin.set_fact:
ipaserver_domain: "ipa.test"
when: "'fqdn' not in ansible_facts"
ansible-freeipa-master/tests/environment/ 0000775 0000000 0000000 00000000000 14600563364 0021112 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/environment/test_locale.yml 0000664 0000000 0000000 00000001533 14600563364 0024135 0 ustar 00root root 0000000 0000000 ---
- name: Test language variations
hosts: ipaserver
tasks:
- name: Ensure a host is not present, with language set to "de_DE".
ipahost:
ipaadmin_password: SomeADMINpassword
name: nonexistent
state: absent
environment:
LANGUAGE: "de_DE"
register: result
failed_when: result.failed or result.changed
- name: Ensure a host is not present, with language set to "C".
ipahost:
ipaadmin_password: SomeADMINpassword
name: nonexistent
state: absent
environment:
LANGUAGE: "C"
register: result
failed_when: result.failed or result.changed
- name: Ensure a host is not present, using controller language.
ipahost:
ipaadmin_password: SomeADMINpassword
name: nonexistent
state: absent
register: result
failed_when: result.failed or result.changed
ansible-freeipa-master/tests/external-signed-ca-with-automatic-copy/ 0000775 0000000 0000000 00000000000 14600563364 0026125 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/external-signed-ca-with-automatic-copy/external-ca.sh 0000664 0000000 0000000 00000003415 14600563364 0030667 0 ustar 00root root 0000000 0000000 #!/bin/bash -eu
master=$1
if [ -z "$master" ]; then
echo "ERROR: master is not set"
echo
echo "usage: $0 master-fqdn domain"
exit 0;
fi
PASSWORD="SomeCApassword.123"
DBDIR="${master}-nssdb"
PWDFILE="$DBDIR/pwdfile.txt"
NOISE="$DBDIR/noise.txt"
domain=$2
if [ -z "$domain" ]; then
echo "ERROR: domain is not set"
echo
echo "usage: $0 master-fqdn domain"
exit 0;
fi
if [ ! -f "${master}-ipa.csr" ]; then
echo "ERROR: ${master}-ipa.csr missing"
exit 1;
fi
ROOT_KEY_ID=0x$(dd if=/dev/urandom bs=20 count=1 | xxd -p)
IPA_CA_KEY_ID=0x$(dd if=/dev/urandom bs=20 count=1 | xxd -p)
# Prepare a new NSS database to serve us as an external CA
rm -rf "$DBDIR"
mkdir "$DBDIR"
echo "$PASSWORD" > "$PWDFILE"
dd count=10 bs=1024 if=/dev/random of="$NOISE" 2>/dev/null
certutil -N -d "$DBDIR" -f "$PWDFILE"
# Generate a CA certificate
echo -e "0\n1\n5\n6\n9\ny\ny\n\ny\n${ROOT_KEY_ID}\nn\n" \
| certutil -d "$DBDIR" -f "$PWDFILE" -S -z "$NOISE" -n ca -x -t C,C,C \
-s "CN=PRIMARY,O=$domain" -x -1 -2 --extSKID -m 1
# Change the form of the CSR from PEM to DER for the NSS database
openssl req -outform der -in "${master}-ipa.csr" -out "$DBDIR/req.csr"
# Sign the certificate request
echo -e "0\n1\n5\n6\n9\ny\ny\n\ny\ny\n${ROOT_KEY_ID}\n\n\nn\n${IPA_CA_KEY_ID}\nn\n" \
| certutil -d "$DBDIR" -f "$PWDFILE" -C -z "$NOISE" -c ca \
-i "$DBDIR/req.csr" -o "$DBDIR/external.cer" -1 -2 -3 --extSKID -m 2
openssl x509 -inform der -in "$DBDIR/external.cer" -out "$DBDIR/external.pem"
# Export the NSS CA certificate and add it to a chain file
certutil -L -n ca -d "$DBDIR" -a > "$DBDIR/ca.crt"
openssl x509 -text -in "$DBDIR/external.pem" > "$DBDIR/chain.crt"
openssl x509 -text -in "$DBDIR/ca.crt" >> "$DBDIR/chain.crt"
cp "$DBDIR/chain.crt" "${master}-chain.crt"
install-server-with-external-ca-with-automatic-copy.yml 0000664 0000000 0000000 00000001556 14600563364 0040631 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/external-signed-ca-with-automatic-copy ---
- name: Playbook to configure IPA server step1
hosts: ipaserver
become: true
vars:
ipaserver_external_ca: yes
ipaserver_copy_csr_to_controller: yes
roles:
- role: ipaserver
state: present
- name: Create CA, get /root/ipa.csr signed by your CA, ..
hosts: localhost
tasks:
- name: Run external-ca.sh
ansible.builtin.command: >
/bin/bash
external-ca.sh
"{{ groups.ipaserver[0] }}"
"{{ ipaserver_domain | default(groups.ipaserver[0].split('.')[1:] | join('.')) }}"
args:
chdir: "{{ playbook_dir }}"
- name: Playbook to configure IPA server step2
hosts: ipaserver
become: true
vars:
ipaserver_external_cert_files_from_controller: "{{ groups.ipaserver[0] + '-chain.crt' }}"
#ipaserver_external_ca_file: "{{ groups.ipaserver[0] + '-cacert.asc' }}"
roles:
- role: ipaserver
state: present
ansible-freeipa-master/tests/external-signed-ca-with-automatic-copy/inventory 0000664 0000000 0000000 00000000254 14600563364 0030106 0 ustar 00root root 0000000 0000000 [ipaserver]
ipaserver.test.local
[ipaserver:vars]
ipaadmin_password=SomeADMINpassword
ipadm_password=SomeDMpassword
ipaserver_domain=test.local
ipaserver_realm=TEST.LOCAL
ansible-freeipa-master/tests/external-signed-ca-with-manual-copy/ 0000775 0000000 0000000 00000000000 14600563364 0025414 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/external-signed-ca-with-manual-copy/external-ca.sh 0000777 0000000 0000000 00000000000 14600563364 0042477 2../external-signed-ca-with-automatic-copy/external-ca.sh ustar 00root root 0000000 0000000 install-server-with-external-ca-with-manual-copy.yml 0000664 0000000 0000000 00000002337 14600563364 0037405 0 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/external-signed-ca-with-manual-copy ---
- name: Playbook to configure IPA server step1
hosts: ipaserver
become: true
vars:
ipaserver_external_ca: yes
roles:
- role: ipaserver
state: present
post_tasks:
- name: Copy CSR /root/ipa.csr from node to "{{ groups.ipaserver[0] + '-ipa.csr' }}"
ansible.builtin.fetch:
src: /root/ipa.csr
dest: "{{ groups.ipaserver[0] + '-ipa.csr' }}"
flat: yes
- name: Get /root/ipa.csr, create CA, sign with our CA and copy to node
hosts: localhost
tasks:
- name: Run external-ca.sh
ansible.builtin.command: >
/bin/bash
external-ca.sh
"{{ groups.ipaserver[0] }}"
"{{ ipaserver_domain | default(groups.ipaserver[0].split('.')[1:] | join('.')) }}"
args:
chdir: "{{ playbook_dir }}"
- name: Playbook to configure IPA server step2
hosts: ipaserver
become: true
vars:
ipaserver_external_cert_files: "/root/chain.crt"
#ipaserver_external_ca_file: "cacert.asc"
pre_tasks:
- name: Copy "{{ groups.ipaserver[0] + '-chain.crt' }}" to /root/chain.crt on node
ansible.builtin.copy:
src: "{{ groups.ipaserver[0] + '-chain.crt' }}"
dest: "/root/chain.crt"
force: yes
mode: preserve
roles:
- role: ipaserver
state: present
ansible-freeipa-master/tests/external-signed-ca-with-manual-copy/inventory 0000664 0000000 0000000 00000000254 14600563364 0027375 0 ustar 00root root 0000000 0000000 [ipaserver]
ipaserver.test.local
[ipaserver:vars]
ipaadmin_password=SomeADMINpassword
ipadm_password=SomeDMpassword
ipaserver_domain=test.local
ipaserver_realm=TEST.LOCAL
ansible-freeipa-master/tests/group/ 0000775 0000000 0000000 00000000000 14600563364 0017702 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/group/create_groups_json.yml 0000664 0000000 0000000 00000000471 14600563364 0024322 0 ustar 00root root 0000000 0000000 ---
- name: Create groups.json
hosts: localhost
tasks:
- name: Check if groups.json exists
ansible.builtin.stat:
path: groups.json
register: register_stat_groups
- name: Create groups.json
ansible.builtin.command: /bin/bash groups.sh 500
when: not register_stat_groups.stat.exists
ansible-freeipa-master/tests/group/groups.sh 0000664 0000000 0000000 00000000703 14600563364 0021555 0 ustar 00root root 0000000 0000000 #!/bin/bash -eu
NUM=${1-1000}
FILE="groups.json"
echo "{" > "$FILE"
echo " \"group_list\": [" >> "$FILE"
for i in $(seq 1 "$NUM"); do
{
echo " {"
echo " \"name\": \"group$i\","
echo " \"description\": \"group description $i\""
} >> "$FILE"
if [ "$i" -lt "$NUM" ]; then
echo " }," >> "$FILE"
else
echo " }" >> "$FILE"
fi
done
echo " ]" >> "$FILE"
echo "}" >> "$FILE"
ansible-freeipa-master/tests/group/test_group.yml 0000664 0000000 0000000 00000025755 14600563364 0022636 0 ustar 00root root 0000000 0000000 ---
- name: Test group
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: true
module_defaults:
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
tasks:
# setup
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# GET FQDN_AT_DOMAIN
- name: Get fqdn_at_domain
ansible.builtin.set_fact:
fqdn_at_domain: "{{ ansible_facts['fqdn'] + '@' + ipaserver_realm }}"
# CLEANUP TEST ITEMS
- name: Ensure users user1, user2 and user3 are absent
ipauser:
name: user1,user2,user3
state: absent
- name: Ensure group group3, group2 and group1 are absent
ipagroup:
name: groupren,group3,group2,group1
state: absent
# CREATE TEST ITEMS
- name: Ensure users user1..user3 are present
ipauser:
users:
- name: user1
first: user1
last: Last
- name: user2
first: user2
last: Last
- name: user3
first: user3
last: Last
register: result
failed_when: not result.changed or result.failed
# TESTS
- name: Ensure group1 is present
ipagroup:
name: group1
register: result
failed_when: not result.changed or result.failed
- name: Ensure group1 is present again
ipagroup:
name: group1
register: result
failed_when: result.changed or result.failed
- name: Rename group1 to groupren
ipagroup:
name: group1
rename: groupren
state: renamed
register: result
failed_when: not result.changed or result.failed
- name: Rename group1 to groupren
ipagroup:
name: group1
rename: groupren
state: renamed
register: result
failed_when: not result.failed or "No group 'group1'" not in result.msg
- name: Rename group groupren to groupren
ipagroup:
name: groupren
rename: groupren
state: renamed
register: result
failed_when: result.changed or result.failed
- name: Rename group groupren back to group1
ipagroup:
name: groupren
rename: group1
state: renamed
register: result
failed_when: not result.changed or result.failed
- name: Ensure group2 is present
ipagroup:
name: group2
register: result
failed_when: not result.changed or result.failed
- name: Ensure group2 is present again
ipagroup:
name: group2
register: result
failed_when: result.changed or result.failed
- name: Ensure group3 is present
ipagroup:
name: group3
register: result
failed_when: not result.changed or result.failed
- name: Ensure group3 is present again
ipagroup:
name: group3
register: result
failed_when: result.changed or result.failed
- name: Ensure groups group2 and group3 are present in group group1
ipagroup:
name: group1
group:
- group2
- group3
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure groups group2 and group3 are present in group group1 again
ipagroup:
name: group1
group:
- group2
- group3
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure group3 ia present in group group1
ipagroup:
name: group1
group:
- group3
action: member
register: result
failed_when: result.changed or result.failed
# service
- name: Execute tests if ipa_verison >= 4.7.0
when: ipa_version is version('4.7.0', '>=')
block:
- name: Ensure service "{{ 'HTTP/' + fqdn_at_domain }}" is present in group group1
ipagroup:
name: group1
service:
- "{{ 'HTTP/' + fqdn_at_domain }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure service "{{ 'HTTP/' + fqdn_at_domain }}" is present in group group1, again
ipagroup:
name: group1
service:
- "{{ 'HTTP/' + fqdn_at_domain }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure service "{{ 'ldap/' + fqdn_at_domain }}" is present in group group1
ipagroup:
name: group1
service:
- "{{ 'ldap/' + fqdn_at_domain }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure service "{{ 'ldap/' + fqdn_at_domain }}" is present in group group1, again
ipagroup:
name: group1
service:
- "{{ 'ldap/' + fqdn_at_domain }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure service "{{ 'HTTP/' + fqdn_at_domain }}" is absent in group group1
ipagroup:
name: group1
service:
- "{{ 'HTTP/' + fqdn_at_domain }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure service "{{ 'HTTP/' + fqdn_at_domain }}" is absent in group group1, again
ipagroup:
name: group1
service:
- "{{ 'HTTP/' + fqdn_at_domain }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure service "{{ 'ldap/' + fqdn_at_domain }}" is absent in group group1
ipagroup:
name: group1
service:
- "{{ 'ldap/' + fqdn_at_domain }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure service "{{ 'ldap/' + fqdn_at_domain }}" is absent in group group1, again
ipagroup:
name: group1
service:
- "{{ 'ldap/' + fqdn_at_domain }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure services are present in group group1
ipagroup:
name: group1
service:
- "{{ 'HTTP/' + fqdn_at_domain }}"
- "{{ 'ldap/' + fqdn_at_domain }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure services are present in group group1, again
ipagroup:
name: group1
service:
- "{{ 'http/' + fqdn_at_domain }}"
- "{{ 'ldap/' + fqdn_at_domain }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure services are absent in group group1
ipagroup:
name: group1
service:
- "{{ 'HTTP/' + fqdn_at_domain }}"
- "{{ 'LDAP/' + fqdn_at_domain }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure services are absent in group group1, again
ipagroup:
name: group1
service:
- "{{ 'HTTP/' + fqdn_at_domain }}"
- "{{ 'ldap/' + fqdn_at_domain }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
# user
- name: Ensure users user1, user2 and user3 are present in group group1
ipagroup:
name: group1
user:
- user1
- user2
- user3
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure users user1, user2 and user3 are present in group group1 again
ipagroup:
name: group1
user:
- user1
- user2
- user3
action: member
register: result
failed_when: result.changed or result.failed
#- ipagroup:
# name: group1
# user:
# - user7
# action: member
- name: Ensure user user7 is absent in group group1
ipagroup:
name: group1
user:
- user7
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure group group4 is absent
ipagroup:
name: group4
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure groups group3, group2, and group1 are absent
ipagroup:
name: group3,group2,group1
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure group group1 is present
ipagroup:
name: group1
register: result
failed_when: not result.changed or result.failed
- name: Ensure users user1, user2 are present in group group1
ipagroup:
name: group1
user:
- user1
- user2
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure users user1, user2 and user3 are present in group group1
ipagroup:
name: group1
user:
- user1
- user2
- user3
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure users user1, user2 are present in group group1, again
ipagroup:
name: group1
user:
- user1
- user2
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure users user1, user2 and user3 are present in group group1, again
ipagroup:
name: group1
user:
- user1
- user2
- user3
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure group group1 is absent
ipagroup:
name: group1
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure group group1 with users user1, user2 is present
ipagroup:
name: group1
user:
- user1
- user2
register: result
failed_when: not result.changed or result.failed
- name: Ensure group group1 with users user1, user2 and user3 is present
ipagroup:
name: group1
user:
- user1
- user2
- user3
register: result
failed_when: not result.changed or result.failed
- name: Ensure group group1 with users user1, user2 and user3 is present, again
ipagroup:
name: group1
user:
- user1
- user2
- user3
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure only users user1, user2 are present in group group1
ipagroup:
name: group1
user:
- user1
- user2
register: result
failed_when: not result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure group group3, group2 and group1 are absent
ipagroup:
name: group3,group2,group1
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure users user1, user2 and user3 are absent
ipauser:
name: user1,user2,user3
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-master/tests/group/test_group_case_insensitive.yml 0000664 0000000 0000000 00000030534 14600563364 0026240 0 ustar 00root root 0000000 0000000 ---
- name: Test group members case insensitive
hosts: ipaserver
become: true
gather_facts: false
module_defaults:
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
vars:
test_users:
- { name: useR1, first: user1, last: last }
- { name: User2, first: user2, last: last }
user_names: "{{ test_users | map(attribute='name') }}"
test_groups:
- name: Group1
- name: Group2
group_names: "{{ test_groups | map(attribute='name') }}"
tasks:
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Test in all supported versions of IPA
block:
# setup environment
- name: Ensure testgroup is absent
ipagroup:
name: testgroup
state: absent
- name: Ensure test users are present
ipauser:
users: "{{ test_users }}"
- name: Ensure test groups are present
ipagroup:
groups: "{{ test_groups }}"
# tests
- name: Test group presence with user members
vars:
test_cases:
- { id: 1, value: "{{ user_names[0] | lower }}", expected: true }
- { id: 2, value: "{{ user_names[0] | upper }}", expected: false }
- { id: 3, value: "{{ user_names[0] }}", expected: false }
- { id: 4, value: "{{ user_names }}", expected: true }
- { id: 5, value: "{{ user_names | upper }}", expected: false }
- { id: 6, value: "{{ user_names | lower }}", expected: false }
- { id: 7, value: "{{ user_names[1] }}", expected: true }
- { id: 8, value: "{{ user_names[1] | upper }}", expected: false }
- { id: 9, value: "{{ user_names[1] | lower }}", expected: false }
- { id: 10, value: [], expected: true }
block:
- name: Ensure group with user parameter present
ipagroup:
name: testgroup
user: "{{ item.value }}"
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "Test id: {{ item.id }}"
- name: Test group presence with group parameter
vars:
test_cases:
- { id: 1, value: "{{ group_names[0] | lower }}", expected: true }
- { id: 2, value: "{{ group_names[0] | upper }}", expected: false }
- { id: 3, value: "{{ group_names[0] }}", expected: false }
- { id: 4, value: "{{ group_names }}", expected: true }
- { id: 5, value: "{{ group_names | upper }}", expected: false }
- { id: 6, value: "{{ group_names | lower }}", expected: false }
- { id: 7, value: "{{ group_names[1] }}", expected: true }
- { id: 8, value: "{{ group_names[1] | upper }}", expected: false }
- { id: 9, value: "{{ group_names[1] | lower }}", expected: false }
- { id: 10, value: [], expected: true }
block:
- name: Ensure group with group present
ipagroup:
name: testgroup
group: "{{ item.value }}"
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "Test id: {{ item.id }}"
- name: Test group with group and user parameters, action member
vars:
test_cases:
- { id: 1, user: "{{ user_names }}", group: "{{ group_names }}", expected: true }
- { id: 2, user: "{{ user_names[0] }}", state: "absent", expected: true }
- { id: 3, user: "{{ user_names[1] }}", state: "present", expected: false }
- { id: 4, user: "{{ user_names[1] | upper }}", state: "present", expected: false }
- { id: 5, user: "{{ user_names[1] | lower }}", state: "present", expected: false }
- { id: 6, group: "{{ group_names[0] | upper }}", state: "present", expected: false }
- { id: 7, group: "{{ group_names[0] | lower }}", state: "present", expected: false }
- { id: 8, group: "{{ group_names[0] }}", state: "present", expected: false }
- { id: 9, user: "{{ user_names[0] }}", group: "{{ group_names[0] }}", state: "absent", expected: true }
- { id: 10, user: "{{ user_names[0] | lower }}", group: "{{ group_names[0] | upper }}", state: "absent", expected: false }
- { id: 11, user: "{{ user_names[0] | upper }}", group: "{{ group_names[0] | lower }}", state: "absent", expected: false }
- { id: 12, user: "{{ user_names[0] }}", group: "{{ group_names[0] }}", state: "absent", expected: false }
- { id: 13, group: "{{ group_names[0] | upper }}", state: "present", expected: true }
- { id: 14, group: "{{ group_names[0] | lower }}", state: "present", expected: false }
- { id: 15, group: "{{ group_names[0] }}", state: "present", expected: false }
- { id: 16, group: "{{ group_names[1] | upper }}", state: "present", expected: false }
- { id: 17, group: "{{ group_names[1] | lower }}", state: "present", expected: false }
- { id: 18, group: "{{ group_names[1] }}", state: "present", expected: false }
- { id: 19, user: "{{ user_names[1] | upper }}", state: "present", expected: false }
- { id: 20, user: "{{ user_names[1] | lower }}", state: "present", expected: false }
- { id: 21, user: "{{ user_names[1] }}", state: "present", expected: false }
block:
- name: Ensure group works with group/user attributes and action member
ipagroup:
name: testgroup
user: "{{ item.user | default(omit) }}"
group: "{{ item.group | default(omit) }}"
action: member
state: "{{ item.state | default('present') }}"
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "Test id: {{ item.id }}"
always:
# cleanup
- name: "Ensure test groups test_groups are absent"
ipagroup:
name: "{{ group_names + ['testgroup'] }}"
state: absent
- name: "Ensure test users test_users are absent"
ipauser:
users: "{{ test_users }}"
state: absent
- name: Test in all IPA versions 8.4.4+
when: ipa_version is version('4.8.4', '>=')
block:
# setup environment
- name: Ensure test users are present
ipauser:
users: "{{ test_users }}"
- name: Ensure test groups are present
ipagroup:
groups: "{{ test_groups }}"
# tests
- name: Test group presence with memembermanager_user members
vars:
test_cases:
- { id: 1, value: "{{ user_names[0] | lower }}", expected: true }
- { id: 2, value: "{{ user_names[0] | upper }}", expected: false }
- { id: 3, value: "{{ user_names[0] }}", expected: false }
- { id: 4, value: "{{ user_names }}", expected: true }
- { id: 5, value: "{{ user_names | upper }}", expected: false }
- { id: 6, value: "{{ user_names | lower }}", expected: false }
- { id: 7, value: "{{ user_names[1] }}", expected: true }
- { id: 8, value: "{{ user_names[1] | upper }}", expected: false }
- { id: 9, value: "{{ user_names[1] | lower }}", expected: false }
- { id: 10, value: [], expected: true }
block:
- name: Ensure group with membermanager_user parameter present
ipagroup:
name: testgroup
membermanager_user: "{{ item.value }}"
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "Test id: {{ item.id }}"
- name: Test group presence with membermanager_group parameter
vars:
test_cases:
- { id: 1, value: "{{ group_names[0] | lower }}", expected: true }
- { id: 2, value: "{{ group_names[0] | upper }}", expected: false }
- { id: 3, value: "{{ group_names[0] }}", expected: false }
- { id: 4, value: "{{ group_names }}", expected: true }
- { id: 5, value: "{{ group_names | upper }}", expected: false }
- { id: 6, value: "{{ group_names | lower }}", expected: false }
- { id: 7, value: "{{ group_names[1] }}", expected: true }
- { id: 8, value: "{{ group_names[1] | upper }}", expected: false }
- { id: 9, value: "{{ group_names[1] | lower }}", expected: false }
- { id: 10, value: [], expected: true }
block:
- name: Ensure group with membermanager_group present
ipagroup:
name: testgroup
membermanager_group: "{{ item.value }}"
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "Test id: {{ item.id }}"
- name: Test group with membermanager_group and membermanager_user parameters, action member
vars:
test_cases:
- { id: 1, user: "{{ user_names }}", group: "{{ group_names }}", expected: true }
- { id: 2, user: "{{ user_names[0] }}", state: "absent", expected: true }
- { id: 3, user: "{{ user_names[1] }}", state: "present", expected: false }
- { id: 4, user: "{{ user_names[1] | upper }}", state: "present", expected: false }
- { id: 5, user: "{{ user_names[1] | lower }}", state: "present", expected: false }
- { id: 6, group: "{{ group_names[0] | upper }}", state: "present", expected: false }
- { id: 7, group: "{{ group_names[0] | lower }}", state: "present", expected: false }
- { id: 8, group: "{{ group_names[0] }}", state: "present", expected: false }
- { id: 9, user: "{{ user_names[0] }}", group: "{{ group_names[0] }}", state: "absent", expected: true }
- { id: 10, user: "{{ user_names[0] | lower }}", group: "{{ group_names[0] | upper }}", state: "absent", expected: false }
- { id: 11, user: "{{ user_names[0] | upper }}", group: "{{ group_names[0] | lower }}", state: "absent", expected: false }
- { id: 12, user: "{{ user_names[0] }}", group: "{{ group_names[0] }}", state: "absent", expected: false }
- { id: 13, group: "{{ group_names[0] | upper }}", state: "present", expected: true }
- { id: 14, group: "{{ group_names[0] | lower }}", state: "present", expected: false }
- { id: 15, group: "{{ group_names[0] }}", state: "present", expected: false }
- { id: 16, group: "{{ group_names[1] | upper }}", state: "present", expected: false }
- { id: 17, group: "{{ group_names[1] | lower }}", state: "present", expected: false }
- { id: 18, group: "{{ group_names[1] }}", state: "present", expected: false }
- { id: 19, user: "{{ user_names[1] | upper }}", state: "present", expected: false }
- { id: 20, user: "{{ user_names[1] | lower }}", state: "present", expected: false }
- { id: 21, user: "{{ user_names[1] }}", state: "present", expected: false }
block:
- name: Ensure group works with group/user attributes and action member
ipagroup:
name: testgroup
membermanager_user: "{{ item.user | default(omit) }}"
membermanager_group: "{{ item.group | default(omit) }}"
action: member
state: "{{ item.state | default('present') }}"
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "Test id: {{ item.id }}"
always:
# cleanup
- name: "Ensure test groups test_groups are absent"
ipagroup:
name: "{{ group_names + ['testgroup'] }}"
state: absent
- name: "Ensure test users test_users are absent"
ipauser:
name: "{{ user_names }}"
state: absent
ansible-freeipa-master/tests/group/test_group_client_context.yml 0000664 0000000 0000000 00000004131 14600563364 0025721 0 ustar 00root root 0000000 0000000 ---
- name: Test group
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test group using client context, in client host.
ansible.builtin.import_playbook: test_group.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test group using client context, in server host.
ansible.builtin.import_playbook: test_group.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
- name: Test groups using client context, in client host.
ansible.builtin.import_playbook: test_groups.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test groups using client context, in server host.
ansible.builtin.import_playbook: test_groups.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
- name: Test groups with mixed types using client context, in client host.
ansible.builtin.import_playbook: test_groups_external_nonposix.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test groups with mixed types using client context, in server host.
ansible.builtin.import_playbook: test_groups_external_nonposix.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/group/test_group_external_group_members_no_trust.yml 0000664 0000000 0000000 00000004346 14600563364 0031414 0 ustar 00root root 0000000 0000000 ---
- name: Test external group group members (without trust-ad installed)
hosts: ipaserver
become: true
tasks:
- name: Ensure external test groups are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name:
- externaltestgroup01
- externaltestgroup02
state: absent
- name: Create external test group 01
ipagroup:
ipaadmin_password: SomeADMINpassword
name: externaltestgroup01
external: true
register: result
failed_when: result.failed or not result.changed
- name: Create external test group 02
ipagroup:
ipaadmin_password: SomeADMINpassword
name: externaltestgroup02
external: true
register: result
failed_when: result.failed or not result.changed
- name: Ensure externaltestgroup02 is a member of externaltestgroup01
ipagroup:
ipaadmin_password: SomeADMINpassword
name: externaltestgroup01
action: member
group:
- externaltestgroup02
register: result
failed_when: result.failed or not result.changed
- name: Ensure externaltestgroup02 is a member of externaltestgroup01, again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: externaltestgroup01
action: member
group:
- externaltestgroup02
register: result
failed_when: result.failed or result.changed
- name: Ensure externaltestgroup02 is not a member of externaltestgroup01
ipagroup:
ipaadmin_password: SomeADMINpassword
name: externaltestgroup01
action: member
group:
- externaltestgroup02
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure externaltestgroup02 is not a member of externaltestgroup01, again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: externaltestgroup01
action: member
group:
- externaltestgroup02
state: absent
register: result
failed_when: result.failed or result.changed
- name: Ensure external test groups are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name:
- externaltestgroup01
- externaltestgroup02
state: absent
register: result
failed_when: result.failed or not result.changed
ansible-freeipa-master/tests/group/test_group_external_members.yml 0000664 0000000 0000000 00000006233 14600563364 0026240 0 ustar 00root root 0000000 0000000 ---
- name: Find trust
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Execute group tests if trust test environment is supported
when: trust_test_is_supported | default(false)
block:
- name: Add nonposix group.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
nonposix: yes
register: result
failed_when: result.failed or not result.changed
- name: Set group to be external
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external: yes
register: result
failed_when: result.failed or not result.changed
- name: Add AD users to group
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external_member: "AD\\Domain Users"
register: result
failed_when: result.failed or not result.changed
- name: Add AD users to group, again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external_member: "AD\\Domain Users"
register: result
failed_when: result.failed or result.changed
- name: Remove external group
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Add nonposix, external group, with AD users.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
nonposix: yes
external: yes
external_member: "AD\\Domain Users"
register: result
failed_when: result.failed or not result.changed
- name: Add nonposix, external group, with AD users, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
nonposix: yes
external: yes
external_member: "AD\\Domain Users"
register: result
failed_when: result.failed or result.changed
- name: Remove group
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Add nonposix group.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
nonposix: yes
register: result
failed_when: result.failed or not result.changed
- name: Set group to be external, and add users.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external: yes
external_member: "AD\\Domain Users"
register: result
failed_when: result.failed or not result.changed
- name: Set group to be external, and add users, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external: yes
external_member: "AD\\Domain Users"
register: result
failed_when: result.failed or result.changed
- name: Cleanup environment.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
state: absent
ansible-freeipa-master/tests/group/test_group_external_nonposix.yml 0000664 0000000 0000000 00000021257 14600563364 0026466 0 ustar 00root root 0000000 0000000 ---
- name: Test group
hosts: ipaserver
become: yes
gather_facts: yes
tasks:
- name: Remove testing groups.
ipagroup:
ipaadmin_password: SomeADMINpassword
name:
- extgroup
- nonposixgroup
- posixgroup
state: absent
- name: Ensure test users testuser1, testuser2 and testuser3 are absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: testuser1,testuser2,testuser3
state: absent
- name: Ensure test users testuser1..testuser3 are present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: testuser1
first: testuser1
last: Last
- name: testuser2
first: testuser2
last: Last
- name: testuser3
first: testuser3
last: Last
register: result
failed_when: not result.changed or result.failed
- name: Add nonposix group.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
nonposix: yes
register: result
failed_when: result.failed or not result.changed
- name: Add nonposix group, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
nonposix: yes
register: result
failed_when: result.failed or result.changed
- name: Set group to be external
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external: yes
register: result
failed_when: result.failed or not result.changed
- name: Set group to be external, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external: yes
register: result
failed_when: result.failed or result.changed
- name: Set external group to be non-external.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
external: no
register: result
failed_when: not result.failed or "group can not be non-external" not in result.msg
- name: Set external group to be posix.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup
posix: yes
register: result
failed_when: not result.failed or "Cannot change `external` group" not in result.msg
- name: Add nonposix group.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: posixgroup
nonposix: yes
register: result
failed_when: result.failed or not result.changed
- name: Set group to be posix
ipagroup:
ipaadmin_password: SomeADMINpassword
name: posixgroup
posix: yes
register: result
failed_when: result.failed or not result.changed
- name: Set group to be posix, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: posixgroup
posix: yes
register: result
failed_when: result.failed or result.changed
- name: Set posix group to be external.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: posixgroup
external: yes
register: result
failed_when: not result.failed or "Cannot change `posix` group" not in result.msg
- name: Set posix group to be non-posix.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: posixgroup
posix: no
register: result
failed_when: not result.failed or "Cannot change `posix` group" not in result.msg
- name: Set posix group to be non-posix.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: posixgroup
nonposix: yes
register: result
failed_when: not result.failed or "Cannot change `posix` group" not in result.msg
- name: Add nonposix group.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: nonposixgroup
posix: no
register: result
failed_when: result.failed or not result.changed
- name: Add nonposix group, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: nonposixgroup
nonposix: yes
register: result
failed_when: result.failed or result.changed
# NONPOSIX MEMBER TEST
- name: Ensure users testuser1, testuser2 and testuser3 are present in group nonposixgroup
ipagroup:
ipaadmin_password: SomeADMINpassword
name: nonposixgroup
nonposix: yes
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: not result.changed or result.failed
- name: Ensure users testuser1, testuser2 and testuser3 are present in group nonposixgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: nonposixgroup
nonposix: yes
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: result.changed or result.failed
# POSIX MEMBER TEST
- name: Ensure users testuser1, testuser2 and testuser3 are present in group posixgroup
ipagroup:
ipaadmin_password: SomeADMINpassword
name: posixgroup
posix: yes
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: not result.changed or result.failed
- name: Ensure users testuser1, testuser2 and testuser3 are present in group posixgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: posixgroup
posix: yes
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: result.changed or result.failed
# EXTERNAL MEMBER TEST (REQUIRES AD)
- name: Execute group tests if trust test environment is supported
when: trust_test_is_supported | default(false)
block:
- name: Ensure users testuser1, testuser2 and testuser3 are present in group externalgroup
ipagroup:
ipaadmin_password: SomeADMINpassword
name: externalgroup
external: yes
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: not result.changed or result.failed
- name: Ensure users testuser1, testuser2 and testuser3 are present in group externalgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: externalgroup
external: yes
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: result.changed or result.failed
# CONVERT NONPOSIX TO POSIX GROUP WITH USERS
- name: Ensure nonposix group nonposixgroup as posix
ipagroup:
ipaadmin_password: SomeADMINpassword
name: nonposixgroup
posix: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure nonposix group nonposixgroup as posix, again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: nonposixgroup
posix: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure nonposix group nonposixgroup (now posix) has users still
ipagroup:
ipaadmin_password: SomeADMINpassword
name: nonposixgroup
posix: yes
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: result.changed or result.failed
# FAIL ON COMBINATIONS OF NONPOSIX, POSIX AND EXTERNAL
- name: Fail to ensure group as nonposix and posix
ipagroup:
ipaadmin_password: SomeADMINpassword
name: posixgroup
nonposix: yes
posix: yes
register: result
failed_when: not result.failed or "parameters are mutually exclusive" not in result.msg
- name: Fail to ensure group as nonposix and external
ipagroup:
ipaadmin_password: SomeADMINpassword
name: posixgroup
nonposix: yes
external: yes
register: result
failed_when: not result.failed or "parameters are mutually exclusive" not in result.msg
- name: Fail to ensure group as posix and external
ipagroup:
ipaadmin_password: SomeADMINpassword
name: posixgroup
posix: yes
external: yes
register: result
failed_when: not result.failed or "parameters are mutually exclusive" not in result.msg
# CLEANUP
- name: Remove testing groups.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: extgroup,nonposixgroup,posixgroup
state: absent
- name: Ensure test users testuser1, testuser2 and testuser3 are absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: testuser1,testuser2,testuser3
state: absent
ansible-freeipa-master/tests/group/test_group_idoverrideuser.yml 0000664 0000000 0000000 00000006376 14600563364 0025747 0 ustar 00root root 0000000 0000000 ---
- name: Test group
hosts: ipaserver
become: yes
gather_facts: yes
vars:
ad_user: "{{ test_ad_user | default('AD\\aduser') }}"
ad_domain: "{{ test_ad_domain | default('ad.ipa.test') }}"
tasks:
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Execute tests if ipa_verison >= 4.8.7 and trust test environment is supported
when: ipa_version is version("4.8.7", ">=") and trust_test_is_supported | default(false)
block:
- name: Create idoverrideuser.
ansible.builtin.shell: |
kinit -c idoverride_cache admin <<< SomeADMINpassword
ipa idoverrideuser-add "Default Trust View" {{ ad_user }}
kdestroy -A -q -c idoverride_cache
- name: Remove testing groups.
ipagroup:
ipaadmin_password: SomeADMINpassword
name:
- idovergroup
state: absent
- name: Add group with idoverrideuser.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
idoverrideuser: "{{ ad_user }}"
register: result
failed_when: result.failed or not result.changed
- name: Add group with idoverrideuser, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
idoverrideuser: "{{ ad_user }}"
register: result
failed_when: result.failed or result.changed
- name: Remove idoverrideuser member.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
idoverrideuser: "{{ ad_user }}"
action: member
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Remove idoverrideuser member, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
idoverrideuser: "{{ ad_user }}"
action: member
state: absent
register: result
failed_when: result.failed or result.changed
- name: Add idoverrideuser member.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
idoverrideuser: "{{ ad_user }}"
action: member
register: result
failed_when: result.failed or not result.changed
- name: Add idoverrideuser member, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
idoverrideuser: "{{ ad_user }}"
action: member
register: result
failed_when: result.failed or result.changed
- name: Cleanup idoverrideuser member.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: idovergroup
idoverrideuser: "{{ ad_user }}"
state: absent
- name: Remove testing groups.
ipagroup:
ipaadmin_password: SomeADMINpassword
name:
- idovergroup
state: absent
always:
- name: Remove idoverrideuser.
ansible.builtin.shell:
cmd: |
kinit -c idoverride_cache admin <<< SomeADMINpassword
ipa idoverrideuser-del "Default Trust View" {{ ad_user }}
kdestroy -A -q -c idoverride_cache
ansible-freeipa-master/tests/group/test_group_membermanager.yml 0000664 0000000 0000000 00000016407 14600563364 0025512 0 ustar 00root root 0000000 0000000 ---
- name: Test group membermanagers
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Execute tests if ipa_verison >= 4.8.4
when: ipa_version is version('4.8.4', '>=')
block:
- name: Ensure user manangeruser1 and manageruser2 is absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: manageruser1,manageruser2,unknown_user
state: absent
- name: Ensure group testgroup, managergroup1 and managergroup2 are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup,managergroup1,managergroup2
state: absent
- name: Ensure user manageruser1 and manageruser2 are present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: manageruser1
first: manageruser1
last: Last1
- name: manageruser2
first: manageruser2
last: Last2
register: result
failed_when: not result.changed or result.failed
- name: Ensure testgroup is present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
register: result
failed_when: not result.changed or result.failed
- name: Ensure managergroup1 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: managergroup1
register: result
failed_when: not result.changed or result.failed
- name: Ensure managergroup2 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: managergroup2
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager user1 is present for testgroup
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_user: manageruser1
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager user1 is present for testgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_user: manageruser1
register: result
failed_when: result.changed or result.failed
- name: Ensure membermanager group1 is present for testgroup
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_group: managergroup1
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager group1 is present for testgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_group: managergroup1
register: result
failed_when: result.changed or result.failed
- name: Ensure membermanager user2 and group2 members are present for testgroup
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_user: manageruser2
membermanager_group: managergroup2
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager user2 and group2 members are present for testgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_user: manageruser2
membermanager_group: managergroup2
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure membermanager user and group members are present for testgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_user: manageruser1,manageruser2
membermanager_group: managergroup1,managergroup2
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure membermanager user1 and group1 members are absent for testgroup
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_user: manageruser1
membermanager_group: managergroup1
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager user1 and group1 members are absent for testgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_user: manageruser1
membermanager_group: managergroup1
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure membermanager user1 and group1 members are present for testgroup
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_user: manageruser1
membermanager_group: managergroup1
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager user1 and group1 members are present for testgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_user: manageruser1
membermanager_group: managergroup1
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure membermanager user and group members are absent for testgroup
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_user: manageruser1,manageruser2
membermanager_group: managergroup1,managergroup2
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager user and group members are absent for testgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_user: manageruser1,manageruser2
membermanager_group: managergroup1,managergroup2
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure user manangeruser1 and manageruser2 is absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: manageruser1,manageruser2
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure unknown membermanager_user member failure
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
membermanager_user: unknown_user
action: member
register: result
failed_when: result.changed or "no such entry" not in result.msg or not result.failed
- name: Ensure group testgroup, managergroup1 and managergroup2 are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name: testgroup,managergroup1,managergroup2
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-master/tests/group/test_groups.yml 0000664 0000000 0000000 00000011662 14600563364 0023011 0 ustar 00root root 0000000 0000000 ---
- name: Test groups
hosts: "{{ ipa_test_host | default('ipaserver') }}"
gather_facts: true
tasks:
# setup
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# GET FQDN_AT_DOMAIN
- name: Get fqdn_at_domain
ansible.builtin.set_fact:
fqdn_at_domain: "{{ ansible_facts['fqdn'] + '@' + ipaserver_realm }}"
# CLEANUP TEST ITEMS
- name: Remove test groups
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group1,group2,group3,group4,group5,group6,group7,group8,group9,group10,newgroup1,newgroup2
state: absent
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
name: user1,user2,user3
state: absent
# CREATE TEST ITEMS
- name: Users user1..3 present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
first: user1
last: Last
- name: user2
first: user2
last: Last
- name: user3
first: user3
last: Last
# TESTS
- name: Groups group1..10 present
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: group1
- name: group2
user:
- user1
- user2
- user3
- name: group3
group:
- group1
- group2
- name: group4
- name: group5
- name: group6
- name: group7
- name: group8
- name: group9
- name: group10
register: result
failed_when: not result.changed or result.failed
- name: Groups group1..10 present again
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: group1
- name: group2
- name: group3
- name: group4
- name: group5
- name: group6
- name: group7
- name: group8
- name: group9
- name: group10
register: result
failed_when: result.changed or result.failed
# failed_when: not result.failed has been added as this test needs to
# fail because two groups with the same name should be added in the same
# task.
- name: Duplicate names in groups failure test
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: group1
- name: group2
- name: group3
- name: group3
register: result
failed_when: result.changed or not result.failed or "is used more than once" not in result.msg
- name: Groups/name and name group11 present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group11
groups:
- name: group11
register: result
failed_when: result.changed or not result.failed or "parameters are mutually exclusive" not in result.msg
- name: Groups/name and name are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
register: result
failed_when: result.changed or not result.failed or "one of the following is required" not in result.msg
- name: Name is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name:
register: result
failed_when: result.changed or not result.failed or "At least one name or groups is required" not in result.msg
- name: Only one group can be added at a time using name.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group11,group12
register: result
failed_when: result.changed or not result.failed or "Only one group can be added at a time using 'name'." not in result.msg
- name: Ensure group1 and group2 exist
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: group1
- name: group2
- name: Rename group1 and group2 to newgroup1 and newgroup2, respectively
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: group1
rename: newgroup1
- name: group2
rename: newgroup2
state: renamed
register: result
failed_when: not result.changed or result.failed
- name: Rename newgroup1 and newgroup2 to the same name
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: newgroup1
rename: newgroup1
- name: newgroup2
rename: newgroup2
state: renamed
register: result
failed_when: result.changed or result.failed
- name: Rename newgroup1 and newgroup2 back to group1 and group2, respectively
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: newgroup1
rename: group1
- name: newgroup2
rename: group2
state: renamed
register: result
failed_when: not result.changed or result.failed
- name: Remove test groups
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group1,group2,group3,group4,group5,group6,group7,group8,group9,group10,newgroup1,newgroup2
state: absent
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
name: user1,user2,user3
state: absent
ansible-freeipa-master/tests/group/test_groups_absent.yml 0000664 0000000 0000000 00000001530 14600563364 0024336 0 ustar 00root root 0000000 0000000 ---
- name: Include create_groups_json.yml
ansible.builtin.import_playbook: create_groups_json.yml
- name: Test groups absent
hosts: ipaserver
gather_facts: false
tasks:
- name: Include groups.json
ansible.builtin.include_vars:
file: groups.json
- name: Initialize groups_names
ansible.builtin.set_fact:
groups_names: []
- name: Create dict with group names
ansible.builtin.set_fact:
groups_names: "{{ groups_names | default([]) + [{'name': item.name}] }}"
loop: "{{ group_list }}"
- name: Groups absent len:{{ group_list | length }}
ipagroup:
ipaadmin_password: SomeADMINpassword
groups: "{{ groups_names }}"
state: absent
- name: Remove groups.json
hosts: localhost
tasks:
- name: Remove groups.json
ansible.builtin.file:
state: absent
path: groups.json
ansible-freeipa-master/tests/group/test_groups_external_nonposix.yml 0000664 0000000 0000000 00000026067 14600563364 0026655 0 ustar 00root root 0000000 0000000 ---
- name: Test multiple external and nonposix groups
hosts: "{{ ipa_test_host | default('ipaserver') }}"
gather_facts: true
tasks:
# setup
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# GET FQDN_AT_DOMAIN
- name: Get fqdn_at_domain
ansible.builtin.set_fact:
fqdn_at_domain: "{{ ansible_facts['fqdn'] + '@' + ipaserver_realm }}"
# CLEANUP TEST ITEMS
- name: Remove testing groups.
ipagroup:
ipaadmin_password: SomeADMINpassword
name:
- extgroup
- nonposixgroup
- posixgroup
- fail_group
- group_1
- posix_group_1
- nonposix_group_1
- external_group_1
- external_group_2
state: absent
- name: Ensure test users testuser1, testuser2 and testuser3 are absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: testuser1,testuser2,testuser3
state: absent
# CREATE TEST ITEMS
- name: Ensure test users testuser1..testuser3 are present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: testuser1
first: testuser1
last: Last
- name: testuser2
first: testuser2
last: Last
- name: testuser3
first: testuser3
last: Last
register: result
failed_when: not result.changed or result.failed
- name: Add nonposix group.
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: extgroup
nonposix: true
register: result
failed_when: result.failed or not result.changed
- name: Add nonposix group, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: extgroup
nonposix: true
register: result
failed_when: result.failed or result.changed
- name: Set group to be external
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: extgroup
external: true
register: result
failed_when: result.failed or not result.changed
- name: Set group to be external, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: extgroup
external: true
register: result
failed_when: result.failed or result.changed
- name: Set external group to be non-external.
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: extgroup
external: false
register: result
failed_when: not result.failed or "group can not be non-external" not in result.msg
- name: Set external group to be posix.
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: extgroup
posix: true
register: result
failed_when: not result.failed or "Cannot change `external` group" not in result.msg
- name: Add nonposix group.
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: posixgroup
nonposix: true
register: result
failed_when: result.failed or not result.changed
- name: Set group to be posix
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: posixgroup
posix: true
register: result
failed_when: result.failed or not result.changed
- name: Set group to be posix, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: posixgroup
posix: true
register: result
failed_when: result.failed or result.changed
- name: Set posix group to be external.
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: posixgroup
external: true
register: result
failed_when: not result.failed or "Cannot change `posix` group" not in result.msg
- name: Set posix group to be non-posix.
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: posixgroup
posix: false
register: result
failed_when: not result.failed or "Cannot change `posix` group" not in result.msg
- name: Set posix group to be non-posix.
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: posixgroup
nonposix: true
register: result
failed_when: not result.failed or "Cannot change `posix` group" not in result.msg
- name: Add nonposix group.
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: nonposixgroup
posix: false
register: result
failed_when: result.failed or not result.changed
- name: Add nonposix group, again.
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: nonposixgroup
nonposix: true
register: result
failed_when: result.failed or result.changed
# NONPOSIX MEMBER TEST
- name: Ensure users testuser1, testuser2 and testuser3 are present in group nonposixgroup
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: nonposixgroup
nonposix: true
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: not result.changed or result.failed
- name: Ensure users testuser1, testuser2 and testuser3 are present in group nonposixgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: nonposixgroup
nonposix: true
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: result.changed or result.failed
# POSIX MEMBER TEST
- name: Ensure users testuser1, testuser2 and testuser3 are present in group posixgroup
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: posixgroup
posix: true
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: not result.changed or result.failed
- name: Ensure users testuser1, testuser2 and testuser3 are present in group posixgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: posixgroup
posix: true
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: result.changed or result.failed
# EXTERNAL MEMBER TEST (REQUIRES AD)
- name: Execute group tests if trust test environment is supported
when: trust_test_is_supported | default(false)
block:
- name: Ensure users testuser1, testuser2 and testuser3 are present in group externalgroup
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: externalgroup
external: true
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: not result.changed or result.failed
- name: Ensure users testuser1, testuser2 and testuser3 are present in group externalgroup again
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: externalgroup
external: true
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: result.changed or result.failed
# CONVERT NONPOSIX TO POSIX GROUP WITH USERS
- name: Ensure nonposix group nonposixgroup as posix
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: nonposixgroup
posix: true
register: result
failed_when: not result.changed or result.failed
- name: Ensure nonposix group nonposixgroup as posix, again
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: nonposixgroup
posix: true
register: result
failed_when: result.changed or result.failed
- name: Ensure nonposix group nonposixgroup (now posix) has users still
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: nonposixgroup
posix: true
user:
- testuser1
- testuser2
- testuser3
register: result
failed_when: result.changed or result.failed
# FAIL ON COMBINATIONS OF NONPOSIX, POSIX AND EXTERNAL
- name: Fail to ensure group as nonposix and posix
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: firstgroup
nonposix: true
posix: false
- name: fail_group
nonposix: true
posix: true
register: result
failed_when: not result.failed or "parameters are mutually exclusive for group `fail_group`" not in result.msg
- name: Fail to ensure group as nonposix and external
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: firstgroup
nonposix: true
posix: false
- name: fail_group
nonposix: true
external: true
register: result
failed_when: not result.failed or "parameters are mutually exclusive for group `fail_group`" not in result.msg
- name: Fail to ensure group as posix and external
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: firstgroup
nonposix: true
posix: false
- name: fail_group
posix: true
external: true
register: result
failed_when: not result.failed or "parameters are mutually exclusive for group `fail_group`" not in result.msg
# GROUPS WITH MIXED TYPES
- name: Adding posix, nonposix and external groups in one batch
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: posix_group_1
posix: true
- name: nonposix_group_1
nonposix: true
- name: external_group_1
external: true
register: result
failed_when: not result.changed or result.failed
- name: Adding non-external and external groups in one batch
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: non_external_group_2
- name: external_group_2
external: true
register: result
failed_when: not result.changed or result.failed
# CLEANUP
- name: Remove testing groups.
ipagroup:
ipaadmin_password: SomeADMINpassword
name:
- extgroup
- nonposixgroup
- posixgroup
- fail_group
- group_1
- posix_group_1
- nonposix_group_1
- external_group_1
- external_group_2
- non_external_group_2
state: absent
- name: Ensure test users testuser1, testuser2 and testuser3 are absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: testuser1,testuser2,testuser3
state: absent
ansible-freeipa-master/tests/group/test_groups_present.yml 0000664 0000000 0000000 00000001715 14600563364 0024547 0 ustar 00root root 0000000 0000000 ---
- name: Include create_groups_json.yml
ansible.builtin.import_playbook: create_groups_json.yml
- name: Test groups present
hosts: ipaserver
gather_facts: false
tasks:
- name: Include groups.json
ansible.builtin.include_vars:
file: groups.json
- name: Groups present len:{{ group_list | length }}
ipagroup:
ipaadmin_password: SomeADMINpassword
groups: "{{ group_list }}"
- name: Initialize groups_names
ansible.builtin.set_fact:
groups_names: []
- name: Create dict with group names
ansible.builtin.set_fact:
groups_names: "{{ groups_names | default([]) + [{'name': item.name}] }}"
loop: "{{ group_list }}"
- name: Remove groups
ipagroup:
ipaadmin_password: SomeADMINpassword
groups: "{{ groups_names }}"
state: absent
- name: Remove groups.json
hosts: localhost
tasks:
- name: Remove groups.json
ansible.builtin.file:
state: absent
path: groups.json
ansible-freeipa-master/tests/group/test_groups_present_slice.yml 0000664 0000000 0000000 00000002221 14600563364 0025717 0 ustar 00root root 0000000 0000000 ---
- name: Include create_groups_json.yml
ansible.builtin.import_playbook: create_groups_json.yml
- name: Test groups present slice
hosts: ipaserver
gather_facts: false
vars:
slice_size: 500
tasks:
- name: Include groups.json
ansible.builtin.include_vars:
file: groups.json
- name: Size of groups slice.
ansible.builtin.debug:
msg: "{{ group_list | length }}"
- name: Groups present
ipagroup:
ipaadmin_password: SomeADMINpassword
groups: "{{ group_list[item : item + slice_size] }}"
loop: "{{ range(0, group_list | length, slice_size) | list }}"
- name: Initialize groups_names
ansible.builtin.set_fact:
groups_names: []
- name: Create dict with group names
ansible.builtin.set_fact:
groups_names: "{{ groups_names | default([]) + [{'name': item.name}] }}"
loop: "{{ group_list }}"
- name: Remove groups
ipagroup:
ipaadmin_password: SomeADMINpassword
groups: "{{ groups_names }}"
state: absent
- name: Remove groups.json
hosts: localhost
tasks:
- name: Remove groups.json
ansible.builtin.file:
state: absent
path: groups.json
ansible-freeipa-master/tests/hbacrule/ 0000775 0000000 0000000 00000000000 14600563364 0020333 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/hbacrule/test_hbacrule.yml 0000664 0000000 0000000 00000060172 14600563364 0023710 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacrule
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
# CLEANUP TEST ITEMS
- name: Ensure test hosts are absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ 'testhost01.' + ipaserver_domain }}"
- "{{ 'testhost02.' + ipaserver_domain }}"
- "{{ 'testhost03.' + ipaserver_domain }}"
- "{{ 'testhost04.' + ipaserver_domain }}"
state: absent
- name: Ensure test hostgroups are absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup01,testhostgroup02,testhostgroup03,testhostgroup04
state: absent
- name: Ensure test users are absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser01,testuser02,testuser03,testuser04
state: absent
- name: Ensure test user groups are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup01,testgroup02,testgroup03,testgroup04
state: absent
- name: Ensure test HBAC Services are absent
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvc01,testhbacsvc02,testhbacsvc03,testhbacsvc04
state: absent
- name: Ensure test HBAC Service Groups are absent
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvcgroup01,testhbacsvcgroup02,testhbacsvcgroup03,testhbacsvcgroup04
state: absent
# CREATE TEST ITEMS
- name: Ensure hosts "{{ 'host[1..4].' + ipaserver_domain }}" are present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
hosts:
- name: "{{ 'testhost01.' + ipaserver_domain }}"
force: yes
- name: "{{ 'testhost02.' + ipaserver_domain }}"
force: yes
- name: "{{ 'testhost03.' + ipaserver_domain }}"
force: yes
- name: "{{ 'testhost04.' + ipaserver_domain }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group testhostgroup01 is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup01
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group testhostgroup02 is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup02
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group testhostgroup03 is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup03
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group testhostgroup04 is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup04
register: result
failed_when: not result.changed or result.failed
- name: Ensure testusers are present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
users:
- name: testuser01
first: test
last: user01
- name: testuser02
first: test
last: user02
- name: testuser03
first: test
last: user03
- name: testuser04
first: test
last: user04
register: result
failed_when: not result.changed or result.failed
- name: Ensure user group testgroup01 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup01
register: result
failed_when: not result.changed or result.failed
- name: Ensure user group testgroup02 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup02
register: result
failed_when: not result.changed or result.failed
- name: Ensure user group testgroup03 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup03
register: result
failed_when: not result.changed or result.failed
- name: Ensure user group testgroup04 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup04
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service testhbacsvc01 is present
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvc01
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service testhbacsvc02 is present
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvc02
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service testhbacsvc03 is present
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvc03
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service testhbacsvc04 is present
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvc04
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service Group testhbacsvcgroup01 is present
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvcgroup01
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service Group testhbacsvcgroup02 is present
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvcgroup02
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service Group testhbacsvcgroup03 is present
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvcgroup03
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service Group testhbacsvcgroup04 is present
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvcgroup04
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 is absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
state: absent
# ENSURE HBACRULE
- name: Ensure HBAC rule hbacrule01 is present
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC rule hbacrule01 is present again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
register: result
failed_when: result.changed or result.failed
# CHANGE HBACRULE WITH ALL MEMBERS
- name: Ensure HBAC rule hbacrule01 is present with hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost01.' + ipaserver_domain }}"
- "{{ 'testhost02.' + ipaserver_domain }}"
hostgroup: testhostgroup01,testhostgroup02
user: testuser01,testuser02
group: testgroup01,testgroup02
hbacsvc: testhbacsvc01,testhbacsvc02
hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC rule hbacrule01 is present with hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost01.' + ipaserver_domain }}"
- "{{ 'testhost02.' + ipaserver_domain }}"
hostgroup: testhostgroup01,testhostgroup02
user: testuser01,testuser02
group: testgroup01,testgroup02
hbacsvc: testhbacsvc01,testhbacsvc02
hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
register: result
failed_when: result.changed or result.failed
# REMOVE MEMBERS ONE BY ONE
- name: Ensure test HBAC rule hbacrule01 host members are absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost01.' + ipaserver_domain }}"
- "{{ 'testhost02.' + ipaserver_domain }}"
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 host members are absent again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost01.' + ipaserver_domain }}"
- "{{ 'testhost02.' + ipaserver_domain }}"
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 hostgroup members are absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hostgroup: testhostgroup01,testhostgroup02
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 hostgroup members are absent again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hostgroup: testhostgroup01,testhostgroup02
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 user members are absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
user: testuser01,testuser02
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 user members are absent again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
user: testuser01,testuser02
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 user group members are absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
group: testgroup01,testgroup02
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 user group members are absent again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
group: testgroup01,testgroup02
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 hbacsvc members are absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hbacsvc: testhbacsvc01,testhbacsvc02
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 hbacsvc members are absent again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hbacsvc: testhbacsvc01,testhbacsvc02
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are absent again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
state: absent
action: member
register: result
failed_when: result.changed or result.failed
# ADD MEMBERS BACK
- name: Ensure test HBAC rule hbacrule01 host members are present
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost01.' + ipaserver_domain }}"
- "{{ 'testhost02.' + ipaserver_domain }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 host members are present again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost01.' + ipaserver_domain }}"
- "{{ 'testhost02.' + ipaserver_domain }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 hostgroup members are present
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hostgroup: testhostgroup01,testhostgroup02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 hostgroup members are present again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hostgroup: testhostgroup01,testhostgroup02
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 user members are present
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
user: testuser01,testuser02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 user members are present again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
user: testuser01,testuser02
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 user group members are present
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
group: testgroup01,testgroup02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 user group members are present again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
group: testgroup01,testgroup02
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 hbacsvc members are present
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hbacsvc: testhbacsvc01,testhbacsvc02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 hbacsvc members are present again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hbacsvc: testhbacsvc01,testhbacsvc02
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are present
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are present again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
action: member
register: result
failed_when: result.changed or result.failed
# CHANGE TO DIFFERENT MEMBERS
- name: Ensure HBAC rule hbacrule01 is present with different hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost03.' + ipaserver_domain }}"
- "{{ 'testhost04.' + ipaserver_domain }}"
hostgroup: testhostgroup03,testhostgroup04
user: testuser03,testuser04
group: testgroup03,testgroup04
hbacsvc: testhbacsvc03,testhbacsvc04
hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC rule hbacrule01 is present with different hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost03.' + ipaserver_domain }}"
- "{{ 'testhost04.' + ipaserver_domain }}"
hostgroup: testhostgroup03,testhostgroup04
user: testuser03,testuser04
group: testgroup03,testgroup04
hbacsvc: testhbacsvc03,testhbacsvc04
hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04
register: result
failed_when: result.changed or result.failed
# ENSURE OLD TEST MEMBERS ARE ABSENT
- name: Ensure HBAC rule hbacrule01 members (same) are present
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost01.' + ipaserver_domain }}"
- "{{ 'testhost02.' + ipaserver_domain }}"
hostgroup: testhostgroup01,testhostgroup02
user: testuser01,testuser02
group: testgroup01,testgroup02
hbacsvc: testhbacsvc01,testhbacsvc02
hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02
state: absent
action: member
register: result
failed_when: result.changed or result.failed
# ENSURE NEW TEST MEMBERS ARE ABSENT
- name: Ensure HBAC rule hbacrule01 members are absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost03.' + ipaserver_domain }}"
- "{{ 'testhost04.' + ipaserver_domain }}"
hostgroup: testhostgroup03,testhostgroup04
user: testuser03,testuser04
group: testgroup03,testgroup04
hbacsvc: testhbacsvc03,testhbacsvc04
hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC rule hbacrule01 members are absent again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost03.' + ipaserver_domain }}"
- "{{ 'testhost04.' + ipaserver_domain }}"
hostgroup: testhostgroup03,testhostgroup04
user: testuser03,testuser04
group: testgroup03,testgroup04
hbacsvc: testhbacsvc03,testhbacsvc04
hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04
state: absent
action: member
register: result
failed_when: result.changed or result.failed
# ENSURE SIMPLE HOSTNAMES MATCH
- name: Ensure HBAC rule hbacrule01 simple host members are usable
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "testhost01"
- "testhost03"
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC rule hbacrule01 simple host members are usable again (and match)
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "testhost01"
- "testhost03"
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure test HBAC rule hbacrule01 is absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
state: absent
- name: Ensure test hosts are absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ 'testhost01.' + ipaserver_domain }}"
- "{{ 'testhost02.' + ipaserver_domain }}"
- "{{ 'testhost03.' + ipaserver_domain }}"
- "{{ 'testhost04.' + ipaserver_domain }}"
state: absent
- name: Ensure test hostgroups are absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup01,testhostgroup02,testhostgroup03,testhostgroup04
state: absent
- name: Ensure test users are absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser01,testuser02,testuser03,testuser04
state: absent
- name: Ensure test user groups are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup01,testgroup02,testgroup03,testgroup04
state: absent
- name: Ensure test HBAC Services are absent
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvc01,testhbacsvc02,testhbacsvc03,testhbacsvc04
state: absent
- name: Ensure test HBAC Service Groups are absent
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvcgroup01,testhbacsvcgroup02,testhbacsvcgroup03,testhbacsvcgroup04
state: absent
ansible-freeipa-master/tests/hbacrule/test_hbacrule_categories.yml 0000664 0000000 0000000 00000012415 14600563364 0026112 0 ustar 00root root 0000000 0000000 ---
- name: Test HBAC rule user category
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC rules are absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name:
- testrule
state: absent
- name: Ensure HBAC rule is present, with usercategory 'all'
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
usercategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC rule is present, with usercategory 'all', again.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
usercategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure HBAC rule is present, with no usercategory.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
usercategory: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC rule is present, with no usercategory, again.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
usercategory: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure HBAC rule is present, with hostcategory 'all'
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
hostcategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC rule is present, with hostcategory 'all', again.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
hostcategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure HBAC rule is present, with no hostcategory.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
hostcategory: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC rule is present, with no hostcategory, again.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
hostcategory: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure HBAC rule is present, with servicecategory 'all'
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
servicecategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC rule is present, with servicecategory 'all', again.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
servicecategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure HBAC rule is present, with no servicecategory.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
servicecategory: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC rule is present, with no servicecategory, again.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
servicecategory: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure `user` cannot be added if usercategory is `all`.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allusers
user: shouldfail01
usercategory: "all"
register: result
failed_when: not result.failed or "Users cannot be added when user category='all'" not in result.msg
- name: Ensure `group` cannot be added if usercategory is `all`.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allusers
group: shouldfail01
usercategory: "all"
register: result
failed_when: not result.failed or "Users cannot be added when user category='all'" not in result.msg
- name: Ensure `host` cannot be added if hostcategory is `all`.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allusers
host: host.shouldfail.com
hostcategory: "all"
register: result
failed_when: not result.failed or "Hosts cannot be added when host category='all'" not in result.msg
- name: Ensure `hostgroup` cannot be added if hostcategory is `all`.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allusers
hostgroup: shouldfail_hostgroup
hostcategory: "all"
register: result
failed_when: not result.failed or "Hosts cannot be added when host category='all'" not in result.msg
- name: Ensure `hbacsvc` cannot be added if hbacsvccategory is `all`.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allusers
hbacsvc: "HTTP/fail.example.com"
servicecategory: "all"
register: result
failed_when: not result.failed or "Services cannot be added when service category='all'" not in result.msg
- name: Ensure `hbacsvcgroup` cannot be added if hbacsvccategory is `all`.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: allusers
hbacsvcgroup: shouldfail_svcgroup
servicecategory: "all"
register: result
failed_when: not result.failed or "Services cannot be added when service category='all'" not in result.msg
- name: Ensure HBAC rules are absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name:
- testrule
state: absent
ansible-freeipa-master/tests/hbacrule/test_hbacrule_client_context.yml 0000664 0000000 0000000 00000002427 14600563364 0027011 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacrule
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test hbacrule using client context, in client host.
ansible.builtin.import_playbook: test_hbacrule.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test hbacrule using client context, in server host.
ansible.builtin.import_playbook: test_hbacrule.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/hbacrule/test_hbacrule_member_case_insensitive.yml 0000664 0000000 0000000 00000041046 14600563364 0030651 0 ustar 00root root 0000000 0000000 ---
- name: Test group
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: yes
vars:
user_list:
- User1
- uSer2
- usEr3
group_list:
- Group1
- gRoup2
- grOup3
host_list:
- HoSt01
- hOsT02
hostgroup_list:
- TestHostGroup
hbacsvc_list:
- Svc1
- sVC2
hbacsvcgroup_list:
- sVCgrOUp1
tasks:
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Test hbacrule member case insensitive
block:
# setup
- name: Ensure test hbacrule is absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
state: absent
- name: Ensure test users are present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: "{{ item }}"
first: First
last: Last
with_items: "{{ user_list }}"
- name: Ensure test groups are present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
with_items: "{{ group_list }}"
- name: Ensure test hosts are present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}.{{ ipaserver_domain }}"
force: yes
with_items: "{{ host_list }}"
- name: Ensure test hostgroups are present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
with_items: "{{ hostgroup_list }}"
- name: Ensure test hbac services are present
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
with_items: "{{ hbacsvc_list }}"
- name: Ensure test hbac service groups are present
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
with_items: "{{ hbacsvcgroup_list }}"
# Test with action: hbacrule
- name: Check if hbacrule present with members would trigger changes, mixed case
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
hbacsvc:
- "{{ hbacsvc_list[0] }}"
- "{{ hbacsvc_list[1] }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] }}"
- Sudo
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure hbacrule is present with members, mixed case
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
hbacsvc:
- "{{ hbacsvc_list[0] }}"
- "{{ hbacsvc_list[1] }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] }}"
- Sudo
register: result
failed_when: not result.changed or result.failed
- name: Check if hbacrule present with members would not trigger changes, mixed case
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
hbacsvc:
- "{{ hbacsvc_list[0] }}"
- "{{ hbacsvc_list[1] }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] }}"
- Sudo
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure hbacrule is present with members, lowercase
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] | lower }}"
- "{{ user_list[2] | lower }}"
group:
- "{{ group_list[1] | lower }}"
- "{{ group_list[2] | lower }}"
host:
- "{{ host_list[0] | lower }}"
- "{{ host_list[1] | lower }}"
hostgroup:
- "{{ hostgroup_list[0] | lower }}"
hbacsvc:
- "{{ hbacsvc_list[0] | lower }}"
- "{{ hbacsvc_list[1] | lower }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] | lower }}"
- sudo
register: result
failed_when: result.changed or result.failed
- name: Ensure hbacrule is present with members, upercase
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] | upper }}"
- "{{ user_list[2] | upper }}"
group:
- "{{ group_list[1] | upper }}"
- "{{ group_list[2] | upper }}"
host:
- "{{ host_list[0] | upper }}"
- "{{ host_list[1] | upper }}"
hostgroup:
- "{{ hostgroup_list[0] | upper }}"
hbacsvc:
- "{{ hbacsvc_list[0] | upper }}"
- "{{ hbacsvc_list[1] | upper }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] | upper }}"
- SUDO
register: result
failed_when: result.changed or result.failed
- name: Ensure test hbacrule is absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
state: absent
# Test with action: members
- name: Ensure test hbacrule is present
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
- name: Check if hbacrule members present would trigger changes, mixed case
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
hbacsvc:
- "{{ hbacsvc_list[0] }}"
- "{{ hbacsvc_list[1] }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] }}"
- Sudo
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure hbacrule members present, mixed case
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
hbacsvc:
- "{{ hbacsvc_list[0] }}"
- "{{ hbacsvc_list[1] }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] }}"
- Sudo
action: member
register: result
failed_when: not result.changed or result.failed
- name: Check if hbacrule members present would not trigger changes, mixed case
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
hbacsvc:
- "{{ hbacsvc_list[0] }}"
- "{{ hbacsvc_list[1] }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] }}"
- Sudo
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure hbacrule members present, lowercase
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] | lower }}"
- "{{ user_list[2] | lower }}"
group:
- "{{ group_list[1] | lower }}"
- "{{ group_list[2] | lower }}"
host:
- "{{ host_list[0] | lower }}"
- "{{ host_list[1] | lower }}"
hostgroup:
- "{{ hostgroup_list[0] | lower }}"
hbacsvc:
- "{{ hbacsvc_list[0] | lower }}"
- "{{ hbacsvc_list[1] | lower }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] | lower }}"
- sudo
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure hbacrule members present, upercase
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] | upper }}"
- "{{ user_list[2] | upper }}"
group:
- "{{ group_list[1] | upper }}"
- "{{ group_list[2] | upper }}"
host:
- "{{ host_list[0] | upper }}"
- "{{ host_list[1] | upper }}"
hostgroup:
- "{{ hostgroup_list[0] | upper }}"
hbacsvc:
- "{{ hbacsvc_list[0] | upper }}"
- "{{ hbacsvc_list[1] | upper }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] | upper }}"
- SUDO
action: member
register: result
failed_when: result.changed or result.failed
# Test absent members
- name: Check if hbacrule members absent would trigger change, upercase
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] | upper }}"
- "{{ user_list[2] | upper }}"
group:
- "{{ group_list[1] | upper }}"
- "{{ group_list[2] | upper }}"
host:
- "{{ host_list[0] | upper }}"
- "{{ host_list[1] | upper }}"
hostgroup:
- "{{ hostgroup_list[0] | upper }}"
hbacsvc:
- "{{ hbacsvc_list[0] | upper }}"
- "{{ hbacsvc_list[1] | upper }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] | upper }}"
- SUDO
action: member
state: absent
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure hbacrule members are absent, upercase
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] | upper }}"
- "{{ user_list[2] | upper }}"
group:
- "{{ group_list[1] | upper }}"
- "{{ group_list[2] | upper }}"
host:
- "{{ host_list[0] | upper }}"
- "{{ host_list[1] | upper }}"
hostgroup:
- "{{ hostgroup_list[0] | upper }}"
hbacsvc:
- "{{ hbacsvc_list[0] | upper }}"
- "{{ hbacsvc_list[1] | upper }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] | upper }}"
- SUDO
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Check if hbacrule members absent would not trigger change, upercase
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] | upper }}"
- "{{ user_list[2] | upper }}"
group:
- "{{ group_list[1] | upper }}"
- "{{ group_list[2] | upper }}"
host:
- "{{ host_list[0] | upper }}"
- "{{ host_list[1] | upper }}"
hostgroup:
- "{{ hostgroup_list[0] | upper }}"
hbacsvc:
- "{{ hbacsvc_list[0] | upper }}"
- "{{ hbacsvc_list[1] | upper }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] | upper }}"
- SUDO
action: member
state: absent
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure hbacrule members are absent, mixed case
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure hbacrule members are absent, lowercase
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
user:
- "{{ user_list[1] | lower }}"
- "{{ user_list[2] | lower }}"
group:
- "{{ group_list[1] | lower }}"
- "{{ group_list[2] | lower }}"
host:
- "{{ host_list[0] | lower }}"
- "{{ host_list[1] | lower }}"
hostgroup:
- "{{ hostgroup_list[0] | lower }}"
hbacsvc:
- "{{ hbacsvc_list[0] | lower }}"
- "{{ hbacsvc_list[1] | lower }}"
hbacsvcgroup:
- "{{ hbacsvcgroup_list[0] | lower }}"
- sudo
action: member
state: absent
register: result
failed_when: result.changed or result.failed
# Specifically test 'Sudo', as FreeIPA adds a "Sudo" hbacsvcgroup instead of "sudo"
- name: Ensure 'sudo' works as hbacsvcgroup.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: "test_sudo"
hbacsvcgroup:
- sudo
register: result
failed_when: not result.changed or result.failed
- name: Ensure 'sudo' works as hbacsvcgroup, again.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: "test_sudo"
hbacsvcgroup:
- sudo
register: result
failed_when: result.changed or result.failed
- name: Ensure 'sudo' works as hbacsvcgroup, action member.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: "test_sudo"
hbacsvcgroup:
- sudo
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure 'Sudo' works as hbacsvcgroup, action member.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: "test_sudo"
hbacsvcgroup:
- Sudo
register: result
failed_when: result.changed or result.failed
always:
- name: Ensure test hbacrule is absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name:
- testrule
- test_sudo
state: absent
- name: Ensure test users are absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: "{{ item }}"
state: absent
with_items: "{{ user_list }}"
- name: Ensure test groups are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
with_items: "{{ group_list }}"
- name: Ensure test hosts are absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}.{{ ipaserver_domain }}"
state: absent
with_items: "{{ host_list }}"
- name: Ensure test hostgroups are absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
with_items: "{{ hostgroup_list }}"
- name: Ensure test hbac services are absent
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
with_items: "{{ hbacsvc_list }}"
- name: Ensure test hbac service groups are absent
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
with_items: "{{ hbacsvcgroup_list }}"
ansible-freeipa-master/tests/hbacrule/test_hbacrule_member_empty.yml 0000664 0000000 0000000 00000024254 14600563364 0026456 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacrule
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Test hbacrule member empty
block:
# SETUP:
- name: Ensure test HBAC rule is absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
state: absent
- name: Ensure test hosts are present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
hosts:
- name: "{{ 'testhost03.' + ipaserver_domain }}"
force: yes
- name: "{{ 'testhost04.' + ipaserver_domain }}"
force: yes
- name: Ensure test hostgroups are present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ item }}"
with_items:
- testhostgroup03
- testhostgroup04
- name: Ensure test users are present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
users:
- name: testuser03
first: test
last: user03
- name: testuser04
first: test
last: user04
- name: Ensure test groups are present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ item }}"
with_items:
- testgroup03
- testgroup04
- name: Ensure test HBAC Services are present
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ item }}"
with_items:
- testhbacsvc03
- testhbacsvc04
- name: Ensure test HBAC Service Groups are present
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ item }}"
with_items:
- testhbacsvcgroup03
- testhbacsvcgroup04
- name: Ensure test HBAC rule hbacrule01 is absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
state: absent
# Ensure members are empty.
- name: Ensure HBAC rule is present with known members
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost03.' + ipaserver_domain }}"
- "{{ 'testhost04.' + ipaserver_domain }}"
hostgroup: testhostgroup03,testhostgroup04
user: testuser03,testuser04
group: testgroup03,testgroup04
hbacsvc: testhbacsvc03,testhbacsvc04
hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule host is empty
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host: []
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule host is empty, again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host: []
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hostgroup is empty
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hostgroup: []
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hostgroup is empty, again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hostgroup: []
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule user is empty
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
user: []
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule user is empty, again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
user: []
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule group is empty
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
group: []
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule group is empty, again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
group: []
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hbacsvc is empty
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hbacsvc: []
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacsvc is empty, again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hbacsvc: []
register: result
failed_when: result.changed or result.failed
- name: Ensure test HBAC rule hbacsvcgroup is empty
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hbacsvcgroup: []
register: result
failed_when: not result.changed or result.failed
- name: Ensure test HBAC rule hbacsvcgroup is empty, again
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
hbacsvcgroup: []
register: result
failed_when: result.changed or result.failed
- name: Verify HBAC rule is present with only members would not require changes.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host: []
hostgroup: []
user: []
group: []
hbacsvc: []
hbacsvcgroup: []
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Verify HBAC rule is present with known members would require changes.
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
host:
- "{{ 'testhost03.' + ipaserver_domain }}"
- "{{ 'testhost04.' + ipaserver_domain }}"
hostgroup: testhostgroup03,testhostgroup04
user: testuser03,testuser04
group: testgroup03,testgroup04
hbacsvc: testhbacsvc03,testhbacsvc04
hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04
check_mode: yes
register: result
failed_when: not result.changed or result.failed
always:
# CLEANUP
- name: Ensure test HBAC rule is absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hbacrule01
state: absent
- name: Ensure test HBAC Service Groups are absent
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvcgroup01,testhbacsvcgroup02,testhbacsvcgroup03,testhbacsvcgroup04
state: absent
- name: Ensure test HBAC Services are absent
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhbacsvc01,testhbacsvc02,testhbacsvc03,testhbacsvc04
state: absent
- name: Ensure test hostgroups are absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testhostgroup01,testhostgroup02,testhostgroup03,testhostgroup04
state: absent
- name: Ensure test hosts are absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ 'testhost01.' + ipaserver_domain }}"
- "{{ 'testhost02.' + ipaserver_domain }}"
- "{{ 'testhost03.' + ipaserver_domain }}"
- "{{ 'testhost04.' + ipaserver_domain }}"
state: absent
- name: Ensure test user groups are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testgroup01,testgroup02,testgroup03,testgroup04
state: absent
- name: Ensure test users are absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser01,testuser02,testuser03,testuser04
state: absent
ansible-freeipa-master/tests/hbacsvc/ 0000775 0000000 0000000 00000000000 14600563364 0020157 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/hbacsvc/test_hbacsvc.yml 0000664 0000000 0000000 00000003754 14600563364 0023363 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacsvc
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Service for http is absent
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: http,tftp
state: absent
- name: Ensure HBAC Service for http is present
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: http
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service for http is present again
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: http
register: result
failed_when: result.changed or result.failed
- name: Ensure HBAC Service for tftp is present
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: tftp
description: TFTP service
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service for tftp is present again
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: tftp
description: TFTP service
register: result
failed_when: result.changed or result.failed
- name: Ensure HBAC Services for http and tftp are absent
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: http,tftp
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Services for http and tftp are absent again
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: http,tftp
state: absent
register: result
failed_when: result.changed or result.failed
ansible-freeipa-master/tests/hbacsvc/test_hbacsvc_client_context.yml 0000664 0000000 0000000 00000002421 14600563364 0026453 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacsvc
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test hbacsvc using client context, in client host.
ansible.builtin.import_playbook: test_hbacsvc.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test hbacsvc using client context, in server host.
ansible.builtin.import_playbook: test_hbacsvc.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/hbacsvcgroup/ 0000775 0000000 0000000 00000000000 14600563364 0021234 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/hbacsvcgroup/test_hbacsvcgroup.yml 0000664 0000000 0000000 00000006011 14600563364 0025502 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacsvcgroup
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Service Group login is absent
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: login
state: absent
- name: Ensure HBAC Service for sshd is present
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: login
- name: Ensure HBAC Service Group login is present
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: login
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service Group login is present again
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: login
register: result
failed_when: result.changed or result.failed
- name: Ensure HBAC Service sshd is present in HBAC Service Group login
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: login
hbacsvc:
- sshd
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service sshd is present in HBAC Service Group login again
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: login
hbacsvc:
- sshd
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure HBAC Services sshd and foo are absent in HBAC Service Group login
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: login
hbacsvc:
- sshd
- foo
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Services sshd and foo are absent in HBAC Service Group login again
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: login
hbacsvc:
- sshd
- foo
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure HBAC Service Group login is absent
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: login
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure HBAC Service Group login is absent again
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: login
state: absent
register: result
failed_when: result.changed or result.failed
ansible-freeipa-master/tests/hbacsvcgroup/test_hbacsvcgroup_client_context.yml 0000664 0000000 0000000 00000002457 14600563364 0030616 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacsvcgroup
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test hbacsvcgroup using client context, in client host.
ansible.builtin.import_playbook: test_hbacsvcgroup.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test hbacsvcgroup using client context, in server host.
ansible.builtin.import_playbook: test_hbacsvcgroup.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/hbacsvcgroup/test_hbacsvcgroup_member_case_insensitive.yml 0000664 0000000 0000000 00000016764 14600563364 0032464 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacsvcgroup member varying capitalization
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
vars:
hbacsvc_list:
- sVc1
- SvC2
tasks:
- name: Test hbacsvcgroup member case insnsitive
block:
- name: Ensure test hbacsvcgroup is absent
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
state: absent
- name: Ensure test HBAC services are present
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
with_items: "{{ hbacsvc_list }}"
- name: Ensure test hbacsvcgroup is present with duplicate hbacsvc
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc:
- sVc1
- SvC1
register: result
failed_when: not result.changed or result.failed
- name: Ensure test hbacsvc is absent from hbacsvcgroup, with duplicate hbacsvc
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc:
- sVc1
- SvC1
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Check if test hbacsvc absent, again, from hbacsvcgroup, with duplicate hbacsvc, would trigger changes
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc:
- svC1
- SVC1
action: member
state: absent
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure test hbacsvcgroup is absent
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Check if hbacsvcgroup with members would trigger changes, mixed case
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list }}"
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure hbacsvcgroup is present with members, mixed case
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list }}"
register: result
failed_when: not result.changed or result.failed
- name: Check if hbacsvcgroup with members would not trigger changes, mixed case
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list }}"
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure hbacsvcgroup is present with members, lowercase
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list | lower }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure hbacsvcgroup is present with members, uppercase
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list | upper }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure test hbacsvcgroup is absent
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
state: absent
- name: Ensure test hbacsvcgroup is present
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
- name: Check if hbacsvcgroup members would trigger changes, mixed case
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list }}"
action: member
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure hbacsvcgroup has members, mixed case
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Check if hbacsvcgroup members would not trigger changes, mixed case
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list }}"
action: member
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure hbacsvcgroup has members, lowercase
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list | lower }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure hbacsvcgroup has members, uppercase
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list | upper }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Check if hbacsvcgroup members absence would trigger changes, uppercase
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list | upper }}"
action: member
state: absent
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure hbacsvcgroup has members absent, uppercase
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list | upper }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Check if hbacsvcgroup members absence would not trigger changes, uppercase
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list | upper }}"
action: member
state: absent
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure hbacsvcgroup has members absent, mixed case
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure hbacsvcgroup has members absent, lowercase
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
hbacsvc: "{{ hbacsvc_list | lower }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
always:
- name: Ensure test hbac service group is absent
ipahbacsvcgroup:
ipaadmin_password: SomeADMINpassword
name: testgroup
state: absent
- name: Ensure test hbac services are absent
ipahbacsvc:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ hbacsvc_list }}"
state: absent
ansible-freeipa-master/tests/host/ 0000775 0000000 0000000 00000000000 14600563364 0017523 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/host/certificate/ 0000775 0000000 0000000 00000000000 14600563364 0022005 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/host/certificate/test_host_certificate.yml 0000664 0000000 0000000 00000006762 14600563364 0027121 0 ustar 00root root 0000000 0000000 ---
- name: Test host certificates
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
- name: Host test absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ 'test.' + ipaserver_domain }}"
state: absent
- name: Host test present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ 'test.' + ipaserver_domain }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Host test cert members present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ 'test.' + ipaserver_domain }}"
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Host test cert members present again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ 'test.' + ipaserver_domain }}"
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Host test cert members absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ 'test.' + ipaserver_domain }}"
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Host test cert members absent again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ 'test.' + ipaserver_domain }}"
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: Host test absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ 'test.' + ipaserver_domain }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Host test absent again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ 'test.' + ipaserver_domain }}"
state: absent
register: result
failed_when: result.changed or result.failed
- name: Remove certificate files.
ansible.builtin.shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/host/certificate/test_hosts_certificate.yml 0000664 0000000 0000000 00000006602 14600563364 0027275 0 ustar 00root root 0000000 0000000 ---
- name: Test host certificates
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Host test absent
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ 'test.' + ipaserver_domain }}"
state: absent
- name: Host test present
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ 'test.' + ipaserver_domain }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
- name: Host test cert members present
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ 'test.' + ipaserver_domain }}"
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Host test cert members present again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ 'test.' + ipaserver_domain }}"
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Host test cert members absent
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ 'test.' + ipaserver_domain }}"
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Host test cert members absent again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ 'test.' + ipaserver_domain }}"
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: Host test absent
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ 'test.' + ipaserver_domain }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Remove certificate files.
ansible.builtin.shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/host/test_host.yml 0000664 0000000 0000000 00000017215 14600563364 0022270 0 ustar 00root root 0000000 0000000 ---
- name: Test host
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host6_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
host3_fqdn: "{{ 'host3.' + ipaserver_domain }}"
host4_fqdn: "{{ 'host4.' + ipaserver_domain }}"
host5_fqdn: "{{ 'host5.' + ipaserver_domain }}"
host6_fqdn: "{{ 'host6.' + ipaserver_domain }}"
- name: Host absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
- "{{ host4_fqdn }}"
- "{{ host5_fqdn }}"
- "{{ host6_fqdn }}"
update_dns: yes
state: absent
- name: Ensure leftover DNS records for test hosts are not present.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ ipaserver_domain }}"
records:
- name: "host1"
del_all: true
- name: "host2"
del_all: true
- name: "host3"
del_all: true
- name: "host4"
del_all: true
- name: "host5"
del_all: true
- name: "host6"
del_all: true
state: absent
- name: Get IPv4 address prefix from server node
ansible.builtin.set_fact:
ipv4_prefix: "{{ ansible_facts['default_ipv4'].address.split('.')[:-1] |
join('.') }}"
- name: Host "{{ host1_fqdn }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
ip_address: "{{ ipv4_prefix + '.201' }}"
update_dns: yes
reverse: no
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present again
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
ip_address: "{{ ipv4_prefix + '.201' }}"
update_dns: yes
reverse: no
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host2_fqdn }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host2_fqdn }}"
ip_address: "{{ ipv4_prefix + '.202' }}"
update_dns: yes
reverse: no
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host2_fqdn }}" present again
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host2_fqdn }}"
ip_address: "{{ ipv4_prefix + '.202' }}"
update_dns: yes
reverse: no
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host3_fqdn }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host3_fqdn }}"
ip_address: "{{ ipv4_prefix + '.203' }}"
update_dns: yes
reverse: no
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host3_fqdn }}" present again
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host3_fqdn }}"
ip_address: "{{ ipv4_prefix + '.203' }}"
update_dns: yes
reverse: no
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host4_fqdn }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host4_fqdn }}"
ip_address: "{{ ipv4_prefix + '.204' }}"
update_dns: yes
reverse: no
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host4_fqdn }}" present again
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host4_fqdn }}"
ip_address: "{{ ipv4_prefix + '.204' }}"
update_dns: yes
reverse: no
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host5_fqdn }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host5_fqdn }}"
ip_address: "{{ ipv4_prefix + '.205' }}"
update_dns: yes
reverse: no
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host5_fqdn }}" present again
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host5_fqdn }}"
ip_address: "{{ ipv4_prefix + '.205' }}"
update_dns: yes
reverse: no
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host6_fqdn }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host6_fqdn }}"
ip_address: "{{ ipv4_prefix + '.206' }}"
update_dns: yes
reverse: no
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host6_fqdn }}" present again
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host6_fqdn }}"
ip_address: "{{ ipv4_prefix + '.206' }}"
update_dns: yes
reverse: no
register: result
failed_when: result.changed or result.failed
# disabled can only be checked with enabled hosts, all hosts above are
# not enabled.
#- name: Hosts host1..host6 disabled
# ipahost:
# ipaadmin_password: SomeADMINpassword
# ipaapi_context: "{{ ipa_context | default(omit) }}"
# name:
# - "{{ host1_fqdn }}"
# - "{{ host2_fqdn }}"
# - "{{ host3_fqdn }}"
# - "{{ host4_fqdn }}"
# - "{{ host5_fqdn }}"
# - "{{ host6_fqdn }}"
# state: disabled
# register: result
# failed_when: not result.changed or result.failed
#
#- name: Hosts host1..host6 disabled again
# ipahost:
# ipaadmin_password: SomeADMINpassword
# ipaapi_context: "{{ ipa_context | default(omit) }}"
# name:
# - "{{ host1_fqdn }}"
# - "{{ host2_fqdn }}"
# - "{{ host3_fqdn }}"
# - "{{ host4_fqdn }}"
# - "{{ host5_fqdn }}"
# - "{{ host6_fqdn }}"
# state: disabled
# register: result
# failed_when: result.changed or result.failed
- name: Hosts host1..host6 absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
- "{{ host4_fqdn }}"
- "{{ host5_fqdn }}"
- "{{ host6_fqdn }}"
update_dns: yes
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Hosts host1..host6 absent again
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
- "{{ host4_fqdn }}"
- "{{ host5_fqdn }}"
- "{{ host6_fqdn }}"
update_dns: yes
state: absent
register: result
failed_when: result.changed or result.failed
ansible-freeipa-master/tests/host/test_host_allow_create_keytab.yml 0000664 0000000 0000000 00000016714 14600563364 0026353 0 ustar 00root root 0000000 0000000 ---
- name: Test host allow_create_keytab
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Get Realm from server name
ansible.builtin.set_fact:
ipaserver_realm: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') | upper }}"
when: ipaserver_realm is not defined
- name: Set host1_fqdn .. host3_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
host3_fqdn: "{{ 'host3.' + ipaserver_domain }}"
- name: Host host1..., host2... and host3... absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
state: absent
- name: Ensure host-groups hostgroup1 and hostgroup2 absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: hostgroup1,hostgroup2
state: absent
- name: Ensure users user1 and user2 absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
- name: user2
state: absent
- name: Ensure group1 and group2 absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group1,group2
state: absent
- name: Host host2... and host3... present
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host2_fqdn }}"
force: yes
- name: "{{ host3_fqdn }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group hostgroup1 present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: hostgroup1
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group hostgroup2 present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: hostgroup2
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure users user1 and user2 present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
first: First1
last: Last1
- name: user2
first: First2
last: Last2
register: result
failed_when: not result.changed or result.failed
- name: Ensure group1 present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group1
register: result
failed_when: not result.changed or result.failed
- name: Ensure group2 present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group2
register: result
failed_when: not result.changed or result.failed
- name: Host host1... present with allow_create_keytab users,groups,hosts and hostgroups
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
allow_create_keytab_user:
- user1
- user2
allow_create_keytab_group:
- group1
- group2
allow_create_keytab_host:
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup1
- hostgroup2
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Host host1... present with allow_create_keytab users,groups,hosts and hostgroups again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
allow_create_keytab_user:
- user1
- user2
allow_create_keytab_group:
- group1
- group2
allow_create_keytab_host:
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup1
- hostgroup2
force: yes
register: result
failed_when: result.changed or result.failed
- name: Host host1... absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
state: absent
- name: Host host1... present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Host host1... ensure allow_create_keytab users,groups,hosts and hostgroups present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
allow_create_keytab_user:
- user1
- user2
allow_create_keytab_group:
- group1
- group2
allow_create_keytab_host:
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup1
- hostgroup2
action: member
register: result
failed_when: not result.changed or result.failed
- name: Host host1... ensure allow_create_keytab users,groups,hosts and hostgroups present again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
allow_create_keytab_user:
- user1
- user2
allow_create_keytab_group:
- group1
- group2
allow_create_keytab_host:
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup1
- hostgroup2
action: member
register: result
failed_when: result.changed or result.failed
- name: Host host1... ensure allow_create_keytab users,groups,hosts and hostgroups absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
allow_create_keytab_user:
- user1
- user2
allow_create_keytab_group:
- group1
- group2
allow_create_keytab_host:
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup1
- hostgroup2
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Host host1... ensure allow_create_keytab users,groups,hosts and hostgroups absent again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
allow_create_keytab_user:
- user1
- user2
allow_create_keytab_group:
- group1
- group2
allow_create_keytab_host:
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup1
- hostgroup2
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Host host1..., host2... and host3... absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-groups hostgroup1 and hostgroup2 absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: hostgroup1,hostgroup2
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure users user1 and user2 absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
- name: user2
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure group1 and group2 absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group1,group2
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-master/tests/host/test_host_allow_retrieve_keytab.yml 0000664 0000000 0000000 00000017012 14600563364 0026725 0 ustar 00root root 0000000 0000000 ---
- name: Test host allow_retrieve_keytab
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Get Realm from server name
ansible.builtin.set_fact:
ipaserver_realm: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') | upper }}"
when: ipaserver_realm is not defined
- name: Set host1_fqdn .. host3_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
host3_fqdn: "{{ 'host3.' + ipaserver_domain }}"
- name: Host host1..., host2... and host3... absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
state: absent
- name: Ensure host-groups hostgroup1 and hostgroup2 absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: hostgroup1,hostgroup2
state: absent
- name: Ensure users user1 and user2 absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
- name: user2
state: absent
- name: Ensure group1 and group2 absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group1,group2
state: absent
- name: Host host2... and host3... present
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host2_fqdn }}"
force: yes
- name: "{{ host3_fqdn }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group hostgroup1 present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: hostgroup1
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group hostgroup2 present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: hostgroup2
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure users user1 and user2 present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
first: First1
last: Last1
- name: user2
first: First2
last: Last2
register: result
failed_when: not result.changed or result.failed
- name: Ensure group1 present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group1
register: result
failed_when: not result.changed or result.failed
- name: Ensure group2 present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group2
register: result
failed_when: not result.changed or result.failed
- name: Host host1... present with allow_retrieve_keytab users,groups,hosts and hostgroups
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
allow_retrieve_keytab_user:
- user1
- user2
allow_retrieve_keytab_group:
- group1
- group2
allow_retrieve_keytab_host:
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup1
- hostgroup2
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Host host1... present with allow_retrieve_keytab users,groups,hosts and hostgroups again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
allow_retrieve_keytab_user:
- user1
- user2
allow_retrieve_keytab_group:
- group1
- group2
allow_retrieve_keytab_host:
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup1
- hostgroup2
force: yes
register: result
failed_when: result.changed or result.failed
- name: Host host1... absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
state: absent
- name: Host host1... present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Host host1... ensure allow_retrieve_keytab users,groups,hosts and hostgroups present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
allow_retrieve_keytab_user:
- user1
- user2
allow_retrieve_keytab_group:
- group1
- group2
allow_retrieve_keytab_host:
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup1
- hostgroup2
action: member
register: result
failed_when: not result.changed or result.failed
- name: Host host1... ensure allow_retrieve_keytab users,groups,hosts and hostgroups present again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
allow_retrieve_keytab_user:
- user1
- user2
allow_retrieve_keytab_group:
- group1
- group2
allow_retrieve_keytab_host:
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup1
- hostgroup2
action: member
register: result
failed_when: result.changed or result.failed
- name: Host host1... ensure allow_retrieve_keytab users,groups,hosts and hostgroups absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
allow_retrieve_keytab_user:
- user1
- user2
allow_retrieve_keytab_group:
- group1
- group2
allow_retrieve_keytab_host:
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup1
- hostgroup2
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Host host1... ensure allow_retrieve_keytab users,groups,hosts and hostgroups absent again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
allow_retrieve_keytab_user:
- user1
- user2
allow_retrieve_keytab_group:
- group1
- group2
allow_retrieve_keytab_host:
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup1
- hostgroup2
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Host host1..., host2... and host3... absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-groups hostgroup1 and hostgroup2 absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: hostgroup1,hostgroup2
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure users user1 and user2 absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
- name: user2
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure group1 and group2 absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group1,group2
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-master/tests/host/test_host_bool_params.yml 0000664 0000000 0000000 00000007232 14600563364 0024644 0 ustar 00root root 0000000 0000000 ---
- name: Test host bool parameters
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host6_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
- name: Host absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
update_dns: yes
state: absent
- name: Host "{{ host1_fqdn }}" present with requires_pre_auth, ok_as_delegate and ok_to_auth_as_delegate
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
force: yes
requires_pre_auth: yes
ok_as_delegate: yes
ok_to_auth_as_delegate: yes
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present with requires_pre_auth, ok_as_delegate and ok_to_auth_as_delegate again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
requires_pre_auth: yes
ok_as_delegate: yes
ok_to_auth_as_delegate: yes
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present with requires_pre_auth, ok_as_delegate and ok_to_auth_as_delegate set to no
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
requires_pre_auth: no
ok_as_delegate: no
ok_to_auth_as_delegate: no
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present with requires_pre_auth, ok_as_delegate and ok_to_auth_as_delegate set to no again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
requires_pre_auth: no
ok_as_delegate: no
ok_to_auth_as_delegate: no
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present with requires_pre_auth
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
requires_pre_auth: yes
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present with requires_pre_auth again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
requires_pre_auth: yes
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present with ok_as_delegate
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ok_as_delegate: yes
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present with ok_as_delegate again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ok_as_delegate: yes
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present with ok_to_auth_as_delegate
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ok_to_auth_as_delegate: yes
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present with ok_to_auth_as_delegate again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ok_to_auth_as_delegate: yes
register: result
failed_when: result.changed or result.failed
- name: Host absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
update_dns: yes
state: absent
ansible-freeipa-master/tests/host/test_host_client_context.yml 0000664 0000000 0000000 00000002413 14600563364 0025364 0 ustar 00root root 0000000 0000000 ---
- name: Test host
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test automember using client context, in client host.
ansible.builtin.import_playbook: test_host.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test automember using client context, in server host.
ansible.builtin.import_playbook: test_host.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/host/test_host_empty_string_params.yml 0000664 0000000 0000000 00000004747 14600563364 0026445 0 ustar 00root root 0000000 0000000 ---
- name: Test host
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: yes
gather_facts: yes
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host6_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
# CLEANUP TEST ITEMS
- name: Ensure host "{{ host1_fqdn }}" absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
state: absent
# CREATE TEST ITEMS
- name: Ensure host "{{ host1_fqdn }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
force: yes
register: result
failed_when: not result.changed or result.failed
# TESTS
- name: Ensure host "{{ host1_fqdn }}" present with auth_ind otp and radius
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
auth_ind:
- otp
- radius
register: result
failed_when: not result.changed or result.failed
- name: Ensure host "{{ host1_fqdn }}" present with auth_ind otp and radius, again
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
auth_ind:
- otp
- radius
register: result
failed_when: result.changed or result.failed
- name: Ensure host "{{ host1_fqdn }}" present with empty auth_ind
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
auth_ind: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure host "{{ host1_fqdn }}" present with empty auth_ind, again
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
auth_ind: ""
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure host "{{ host1_fqdn }}" absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
state: absent
ansible-freeipa-master/tests/host/test_host_ipaddresses.yml 0000664 0000000 0000000 00000023253 14600563364 0024655 0 ustar 00root root 0000000 0000000 ---
- name: Test host IP addresses
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host6_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
host3_fqdn: "{{ 'host3.' + ipaserver_domain }}"
- name: Get IPv4 address prefix from server node
ansible.builtin.set_fact:
ipv4_prefix: "{{ ansible_facts['default_ipv4'].address.split('.')[:-1] |
join('.') }}"
- name: Host absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
update_dns: yes
state: absent
- name: Host "{{ host1_fqdn }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.201' }}"
- fe80::20c:29ff:fe02:a1b2
update_dns: yes
reverse: no
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.201' }}"
- fe80::20c:29ff:fe02:a1b2
update_dns: yes
reverse: no
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present again with new IP address
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.211' }}"
- fe80::20c:29ff:fe02:a1b3
- "{{ ipv4_prefix + '.221' }}"
- fe80::20c:29ff:fe02:a1b4
update_dns: yes
reverse: no
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present again with new IP address again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.211' }}"
- fe80::20c:29ff:fe02:a1b3
- "{{ ipv4_prefix + '.221' }}"
- fe80::20c:29ff:fe02:a1b4
update_dns: yes
reverse: no
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" member IPv4 address present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address: "{{ ipv4_prefix + '.201' }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" member IPv4 address present again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address: "{{ ipv4_prefix + '.201' }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" member IPv4 address absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address: "{{ ipv4_prefix + '.201' }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" member IPv4 address absent again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address: "{{ ipv4_prefix + '.201' }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" member IPv6 address present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address: fe80::20c:29ff:fe02:a1b2
action: member
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" member IPv6 address present again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address: fe80::20c:29ff:fe02:a1b2
action: member
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" member IPv6 address absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address: fe80::20c:29ff:fe02:a1b2
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" member IPv6 address absent again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address: fe80::20c:29ff:fe02:a1b2
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" member all ip-addresses absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.211' }}"
- fe80::20c:29ff:fe02:a1b3
- "{{ ipv4_prefix + '.221' }}"
- fe80::20c:29ff:fe02:a1b4
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" all member ip-addresses absent again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.211' }}"
- fe80::20c:29ff:fe02:a1b3
- "{{ ipv4_prefix + '.221' }}"
- fe80::20c:29ff:fe02:a1b4
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Hosts "{{ host1_fqdn }}" and "{{ host2_fqdn }}" present with same IP addresses
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.211' }}"
- fe80::20c:29ff:fe02:a1b3
- "{{ ipv4_prefix + '.221' }}"
- fe80::20c:29ff:fe02:a1b4
- name: "{{ host2_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.211' }}"
- fe80::20c:29ff:fe02:a1b3
- "{{ ipv4_prefix + '.221' }}"
- fe80::20c:29ff:fe02:a1b4
register: result
failed_when: not result.changed or result.failed
- name: Hosts "{{ host1_fqdn }}" and "{{ host2_fqdn }}" present with same IP addresses again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.211' }}"
- fe80::20c:29ff:fe02:a1b3
- "{{ ipv4_prefix + '.221' }}"
- fe80::20c:29ff:fe02:a1b4
- name: "{{ host2_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.211' }}"
- fe80::20c:29ff:fe02:a1b3
- "{{ ipv4_prefix + '.221' }}"
- fe80::20c:29ff:fe02:a1b4
register: result
failed_when: result.changed or result.failed
- name: Hosts "{{ host3_fqdn }}" present with same IP addresses
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host3_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.211' }}"
- fe80::20c:29ff:fe02:a1b3
- "{{ ipv4_prefix + '.221' }}"
- fe80::20c:29ff:fe02:a1b4
register: result
failed_when: not result.changed or result.failed
- name: Hosts "{{ host3_fqdn }}" present with same IP addresses again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host3_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.211' }}"
- fe80::20c:29ff:fe02:a1b3
- "{{ ipv4_prefix + '.221' }}"
- fe80::20c:29ff:fe02:a1b4
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host3_fqdn }}" present with differnt IP addresses
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host3_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.111' }}"
- fe80::20c:29ff:fe02:a1b1
- "{{ ipv4_prefix + '.121' }}"
- fe80::20c:29ff:fe02:a1b2
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host3_fqdn }}" present with different IP addresses again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host3_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.111' }}"
- fe80::20c:29ff:fe02:a1b1
- "{{ ipv4_prefix + '.121' }}"
- fe80::20c:29ff:fe02:a1b2
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host3_fqdn }}" present with old IP addresses
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host3_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.211' }}"
- fe80::20c:29ff:fe02:a1b3
- "{{ ipv4_prefix + '.221' }}"
- fe80::20c:29ff:fe02:a1b4
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host3_fqdn }}" present with old IP addresses again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host3_fqdn }}"
ip_address:
- "{{ ipv4_prefix + '.211' }}"
- fe80::20c:29ff:fe02:a1b3
- "{{ ipv4_prefix + '.221' }}"
- fe80::20c:29ff:fe02:a1b4
register: result
failed_when: result.changed or result.failed
- name: Absent host01.ihavenodns.info test
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: host01.ihavenodns.info
state: absent
register: result
failed_when: result.changed or result.failed
- name: Host absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
update_dns: yes
state: absent
ansible-freeipa-master/tests/host/test_host_managedby_host.yml 0000664 0000000 0000000 00000007426 14600563364 0025337 0 ustar 00root root 0000000 0000000 ---
- name: Test host managedby_host
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host2_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
- name: Host absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
update_dns: yes
state: absent
- name: Host "{{ host1_fqdn }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host2_fqdn }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host2_fqdn }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" managed by "{{ 'host2.' + ipaserver_domain }}"
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
managedby_host: "{{ host2_fqdn }}"
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" managed by "{{ 'host2.' + ipaserver_domain }}" again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
managedby_host: "{{ host2_fqdn }}"
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" managed by "{{ ansible_facts['fqdn'] }}"
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
managedby_host: "{{ ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" managed by "{{ ansible_facts['fqdn'] }}" again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
managedby_host: "{{ ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" not managed by "{{ ansible_facts['fqdn'] }}"
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
managedby_host: "{{ ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" not managed by "{{ ansible_facts['fqdn'] }}" again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
managedby_host: "{{ ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Host "{{ host1_fqdn }}" not managed by "{{ 'host2.' + ipaserver_domain }}"
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
managedby_host: "{{ host2_fqdn }}"
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" not managed by "{{ 'host2.' + ipaserver_domain }}" again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
managedby_host: "{{ host2_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Host absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
update_dns: yes
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-master/tests/host/test_host_no_zone.yml 0000664 0000000 0000000 00000000454 14600563364 0024014 0 ustar 00root root 0000000 0000000 ---
- name: Test host
hosts: ipaserver
become: yes
tasks:
- name: Ensure host with inexistent zone is absent.
ipahost:
ipaadmin_password: SomeADMINpassword
name: host01.absentzone.test
state: absent
register: result
failed_when: result.failed or result.changed
ansible-freeipa-master/tests/host/test_host_principal.yml 0000664 0000000 0000000 00000010446 14600563364 0024330 0 ustar 00root root 0000000 0000000 ---
- name: Test host principal
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Get Realm from server name
ansible.builtin.set_fact:
ipaserver_realm: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') | upper }}"
when: ipaserver_realm is not defined
- name: Set host1_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
- name: Host host1 absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
update_dns: yes
state: absent
- name: Host host1... present with principal host/testhost1...
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Host host1... principal host/host1... present (existing already)
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/host1.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Host host1... principal host/testhost1... present again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
principal: "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Host host1... principal host/testhost1... absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
principal: "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Host host1... principal host/testhost1... absent again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
principal: "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Host host1... principal host/testhost1... and host/myhost1... present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- "{{ 'host/myhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Host host1... principal host/testhost1... and host/myhost1... present again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- "{{ 'host/myhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Host host1... principal host/testhost1... and host/myhost1... absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- "{{ 'host/myhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Host host1... principal host/testhost1... and host/myhost1... absent again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- "{{ 'host/myhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Host host1... absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
update_dns: yes
state: absent
ansible-freeipa-master/tests/host/test_host_random.yml 0000664 0000000 0000000 00000007211 14600563364 0023623 0 ustar 00root root 0000000 0000000 ---
- name: Test ipahost random password generation
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn and host2_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
server_fqdn: "{{ ansible_facts['fqdn'] }}"
- name: Test hosts absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
update_dns: yes
state: absent
- name: Host "{{ host1_fqdn }}" present with random password
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
random: yes
force: yes
update_password: on_create
register: ipahost
failed_when: not ipahost.changed or ipahost.failed
- name: Assert ipahost.host.randompassword is defined.
ansible.builtin.assert:
that:
- ipahost.host.randompassword is defined
- name: Print generated random password
ansible.builtin.debug:
var: ipahost.host.randompassword
- name: Host "{{ host1_fqdn }}" absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
state: absent
- name: Host "{{ host1_fqdn }}" is present with random password using hosts parameter
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
random: yes
force: yes
update_password: on_create
register: ipahost
failed_when: not ipahost.changed or
ipahost.host[host1_fqdn].randompassword is not defined or
ipahost.failed
- name: Host "{{ host1_fqdn }}" absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
state: absent
- name: Hosts "{{ host1_fqdn }}" and "{{ host2_fqdn }}" present with random password
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
random: yes
force: yes
- name: "{{ host2_fqdn }}"
random: yes
force: yes
update_password: on_create
register: ipahost
failed_when: not ipahost.changed or ipahost.failed
- name: Assert randompassword is defined for host1 and host2.
ansible.builtin.assert:
that:
- ipahost.host[host1_fqdn].randompassword is defined
- ipahost.host[host2_fqdn].randompassword is defined
- name: Print generated random password for "{{ host1_fqdn }}"
ansible.builtin.debug:
var: ipahost.host["{{ host1_fqdn }}"].randompassword
- name: Print generated random password for "{{ host2_fqdn }}"
ansible.builtin.debug:
var: ipahost.host["{{ host2_fqdn }}"].randompassword
- name: Enrolled host "{{ server_fqdn }}" fails to set random password with update_password always
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ server_fqdn }}"
random: yes
update_password: always
register: ipahost
failed_when: ipahost.changed or not ipahost.failed
- name: Assert randompassword is not defined for 'ansible_fqdn'.
ansible.builtin.assert:
that:
- ipahost.host[server_fqdn].randompassword is not defined
- "'Password cannot be set on enrolled host' in ipahost.msg"
- name: Hosts "{{ host1_fqdn }}" and "{{ host2_fqdn }}" absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
state: absent
ansible-freeipa-master/tests/host/test_host_reverse.yml 0000664 0000000 0000000 00000007125 14600563364 0024022 0 ustar 00root root 0000000 0000000 ---
- name: Test host
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
- name: Host absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
update_dns: yes
state: absent
- name: Get IPv4 address prefix from server node
ansible.builtin.set_fact:
ipv4_prefix: "{{ ansible_facts['default_ipv4'].address.split('.')[:-1] |
join('.') }}"
- name: Set zone prefixes.
ansible.builtin.set_fact:
zone_ipv6_reverse: "ip6.arpa."
zone_ipv6_reverse_workaround: "d.f.ip6.arpa."
zone_prefix_reverse: "in-addr.arpa"
zone_prefix_reverse_8: "{{ ipv4_prefix.split('.')[2::-1] | join('.') }}.in-addr.arpa"
zone_prefix_reverse_16: "{{ ipv4_prefix.split('.')[1::-1] | join('.') }}.in-addr.arpa"
zone_prefix_reverse_24: "{{ ipv4_prefix.split('.')[::-1] | join('.') }}.in-addr.arpa"
- name: Set zone for reverse address.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
skip_nameserver_check: yes
skip_overlap_check: yes
with_items:
- "{{ zone_ipv6_reverse }}"
- "{{ zone_ipv6_reverse_workaround }}"
- "{{ zone_prefix_reverse }}"
- "{{ zone_prefix_reverse_8 }}"
- "{{ zone_prefix_reverse_16 }}"
- "{{ zone_prefix_reverse_24 }}"
- name: Host "{{ host1_fqdn }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address: "{{ ipv4_prefix + '.201' }}"
update_dns: yes
reverse: yes
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present, again.
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address: "{{ ipv4_prefix + '.201' }}"
update_dns: yes
reverse: yes
register: result
failed_when: result.changed or result.failed
- name: Hosts host1 absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
update_dns: yes
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present with IPv6
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address: "fd00::0001"
update_dns: yes
reverse: yes
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ host1_fqdn }}" present with IPv6, again.
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
ip_address: "fd00::0001"
update_dns: yes
reverse: yes
register: result
failed_when: result.changed or result.failed
- name: Hosts host1 absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
update_dns: yes
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Delete zone for reverse address.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
with_items:
- "{{ zone_ipv6_reverse }}"
- "{{ zone_ipv6_reverse_workaround }}"
- "{{ zone_prefix_reverse }}"
- "{{ zone_prefix_reverse_8 }}"
- "{{ zone_prefix_reverse_16 }}"
- "{{ zone_prefix_reverse_24 }}"
ansible-freeipa-master/tests/host/test_host_sshpubkey.yml 0000664 0000000 0000000 00000022617 14600563364 0024367 0 ustar 00root root 0000000 0000000 ---
- name: Test host sshpubkey
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
- name: Host host1 absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
update_dns: yes
state: absent
- name: Host host1 present
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
update_dns: yes
force: yes
- name: Host host1... present with sshpubkey
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
sshpubkey:
# yamllint disable-line rule:line-length
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqmVDpEX5gnSjKuv97AyzOhaUMMKz8ahOA3GY77tVC4o68KNgMCmDSEG1/kOIaElngNLaCha3p/2iAcU9Bi1tLKUlm2bbO5NHNwHfRxY/3cJtq+/7D1vxJzqThYwI4F9vr1WxyY2+mMTv3pXbfAJoR8Mu06XaEY5PDetlDKjHLuNWF+/O7ZU8PsULTa1dJZFrtXeFpmUoLoGxQBvlrlcPI1zDciCSU24t27Zan5Py2l5QchyI7yhCyMM77KDtj5+AFVpmkb9+zq50rYJAyFVeyUvwjzErvQrKJzYpA0NyBp7vskWbt36M16/M/LxEK7HA6mkcakO3ESWx5MT1LAjvdlnxbWG3787MxweHXuB8CZU+9bZPFBaJ+VQtOfJ7I8eH0S16moPC4ak8FlcFvOH8ERDPWLFDqfy09yaZ7bVIF0//5ZI7Nf3YDe3S7GrBX5ieYuECyP6UNkTx9BRsAQeVvXEc6otzB7iCSnYBMGUGzCqeigoAWaVQUONsSR3Uatks= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: not result.changed or result.failed
- name: Host host1... present with sshpubkey again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
sshpubkey:
# yamllint disable-line rule:line-length
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqmVDpEX5gnSjKuv97AyzOhaUMMKz8ahOA3GY77tVC4o68KNgMCmDSEG1/kOIaElngNLaCha3p/2iAcU9Bi1tLKUlm2bbO5NHNwHfRxY/3cJtq+/7D1vxJzqThYwI4F9vr1WxyY2+mMTv3pXbfAJoR8Mu06XaEY5PDetlDKjHLuNWF+/O7ZU8PsULTa1dJZFrtXeFpmUoLoGxQBvlrlcPI1zDciCSU24t27Zan5Py2l5QchyI7yhCyMM77KDtj5+AFVpmkb9+zq50rYJAyFVeyUvwjzErvQrKJzYpA0NyBp7vskWbt36M16/M/LxEK7HA6mkcakO3ESWx5MT1LAjvdlnxbWG3787MxweHXuB8CZU+9bZPFBaJ+VQtOfJ7I8eH0S16moPC4ak8FlcFvOH8ERDPWLFDqfy09yaZ7bVIF0//5ZI7Nf3YDe3S7GrBX5ieYuECyP6UNkTx9BRsAQeVvXEc6otzB7iCSnYBMGUGzCqeigoAWaVQUONsSR3Uatks= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: result.changed or result.failed
- name: Host host1... present with other sshpubkey
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
sshpubkey:
# yamllint disable-line rule:line-length
- AAAAB3NzaC1yc2EAAAADAQABAAABgQDc8MIjaSrxLYHvu+hduoF4m6NUFSlXZWzYbd3BK4L47/U4eiXoOS6dcfuZJDjmLfOipc7XVp7NADwAgA1yBOAjbeVpXr2tC8w8saZibl75WBOEjDfNroiOh/f/ojrwwHg05QTVSZHs27sU1HBPyCQM/FHVM6EnRfmyiBkEBA/3ca0PJ9UJhWb2XisCaz6y6QcTh4gQnvHzgmEmK31GwiKnmBSEQuj8P5NGCO8RlN3cq3zpRpMDEoBRCjQYicllf/5P43r5OGvS1LhTiAMfyqE37URezNQa7aozBpH1GhIwAmjAtm84jXQjxUgZPYC0aSLuADYErScOP4792r6koH9t/DM5/M+jG2c4PNWynDczUw6Eaxl5E3hU0Ee9UN0Oee7iBnVenS/QMeZNyo5lMA/HXT5lrYiJGTYM0shRjGXXYBbJZhWerguSWDAdUd1gvuGP1nb7/+/Cvb46+HX7zYouS5Ojo0yPzMZ07X142jnKAfx9LnKdMUCwBJzbtoJ91Zc= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: not result.changed or result.failed
- name: Host host1... present with other sshpubkey again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
sshpubkey:
# yamllint disable-line rule:line-length
- AAAAB3NzaC1yc2EAAAADAQABAAABgQDc8MIjaSrxLYHvu+hduoF4m6NUFSlXZWzYbd3BK4L47/U4eiXoOS6dcfuZJDjmLfOipc7XVp7NADwAgA1yBOAjbeVpXr2tC8w8saZibl75WBOEjDfNroiOh/f/ojrwwHg05QTVSZHs27sU1HBPyCQM/FHVM6EnRfmyiBkEBA/3ca0PJ9UJhWb2XisCaz6y6QcTh4gQnvHzgmEmK31GwiKnmBSEQuj8P5NGCO8RlN3cq3zpRpMDEoBRCjQYicllf/5P43r5OGvS1LhTiAMfyqE37URezNQa7aozBpH1GhIwAmjAtm84jXQjxUgZPYC0aSLuADYErScOP4792r6koH9t/DM5/M+jG2c4PNWynDczUw6Eaxl5E3hU0Ee9UN0Oee7iBnVenS/QMeZNyo5lMA/HXT5lrYiJGTYM0shRjGXXYBbJZhWerguSWDAdUd1gvuGP1nb7/+/Cvb46+HX7zYouS5Ojo0yPzMZ07X142jnKAfx9LnKdMUCwBJzbtoJ91Zc= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: result.changed or result.failed
- name: Host host1... present with two sshpubkeys
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
sshpubkey:
# yamllint disable-line rule:line-length
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqmVDpEX5gnSjKuv97AyzOhaUMMKz8ahOA3GY77tVC4o68KNgMCmDSEG1/kOIaElngNLaCha3p/2iAcU9Bi1tLKUlm2bbO5NHNwHfRxY/3cJtq+/7D1vxJzqThYwI4F9vr1WxyY2+mMTv3pXbfAJoR8Mu06XaEY5PDetlDKjHLuNWF+/O7ZU8PsULTa1dJZFrtXeFpmUoLoGxQBvlrlcPI1zDciCSU24t27Zan5Py2l5QchyI7yhCyMM77KDtj5+AFVpmkb9+zq50rYJAyFVeyUvwjzErvQrKJzYpA0NyBp7vskWbt36M16/M/LxEK7HA6mkcakO3ESWx5MT1LAjvdlnxbWG3787MxweHXuB8CZU+9bZPFBaJ+VQtOfJ7I8eH0S16moPC4ak8FlcFvOH8ERDPWLFDqfy09yaZ7bVIF0//5ZI7Nf3YDe3S7GrBX5ieYuECyP6UNkTx9BRsAQeVvXEc6otzB7iCSnYBMGUGzCqeigoAWaVQUONsSR3Uatks= pinky@ipaserver.el81.local # noqa 204
# yamllint disable-line rule:line-length
- AAAAB3NzaC1yc2EAAAADAQABAAABgQDc8MIjaSrxLYHvu+hduoF4m6NUFSlXZWzYbd3BK4L47/U4eiXoOS6dcfuZJDjmLfOipc7XVp7NADwAgA1yBOAjbeVpXr2tC8w8saZibl75WBOEjDfNroiOh/f/ojrwwHg05QTVSZHs27sU1HBPyCQM/FHVM6EnRfmyiBkEBA/3ca0PJ9UJhWb2XisCaz6y6QcTh4gQnvHzgmEmK31GwiKnmBSEQuj8P5NGCO8RlN3cq3zpRpMDEoBRCjQYicllf/5P43r5OGvS1LhTiAMfyqE37URezNQa7aozBpH1GhIwAmjAtm84jXQjxUgZPYC0aSLuADYErScOP4792r6koH9t/DM5/M+jG2c4PNWynDczUw6Eaxl5E3hU0Ee9UN0Oee7iBnVenS/QMeZNyo5lMA/HXT5lrYiJGTYM0shRjGXXYBbJZhWerguSWDAdUd1gvuGP1nb7/+/Cvb46+HX7zYouS5Ojo0yPzMZ07X142jnKAfx9LnKdMUCwBJzbtoJ91Zc= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: not result.changed or result.failed
- name: Host host1... present with two sshpubkeys again
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
sshpubkey:
# yamllint disable-line rule:line-length
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqmVDpEX5gnSjKuv97AyzOhaUMMKz8ahOA3GY77tVC4o68KNgMCmDSEG1/kOIaElngNLaCha3p/2iAcU9Bi1tLKUlm2bbO5NHNwHfRxY/3cJtq+/7D1vxJzqThYwI4F9vr1WxyY2+mMTv3pXbfAJoR8Mu06XaEY5PDetlDKjHLuNWF+/O7ZU8PsULTa1dJZFrtXeFpmUoLoGxQBvlrlcPI1zDciCSU24t27Zan5Py2l5QchyI7yhCyMM77KDtj5+AFVpmkb9+zq50rYJAyFVeyUvwjzErvQrKJzYpA0NyBp7vskWbt36M16/M/LxEK7HA6mkcakO3ESWx5MT1LAjvdlnxbWG3787MxweHXuB8CZU+9bZPFBaJ+VQtOfJ7I8eH0S16moPC4ak8FlcFvOH8ERDPWLFDqfy09yaZ7bVIF0//5ZI7Nf3YDe3S7GrBX5ieYuECyP6UNkTx9BRsAQeVvXEc6otzB7iCSnYBMGUGzCqeigoAWaVQUONsSR3Uatks= pinky@ipaserver.el81.local # noqa 204
# yamllint disable-line rule:line-length
- AAAAB3NzaC1yc2EAAAADAQABAAABgQDc8MIjaSrxLYHvu+hduoF4m6NUFSlXZWzYbd3BK4L47/U4eiXoOS6dcfuZJDjmLfOipc7XVp7NADwAgA1yBOAjbeVpXr2tC8w8saZibl75WBOEjDfNroiOh/f/ojrwwHg05QTVSZHs27sU1HBPyCQM/FHVM6EnRfmyiBkEBA/3ca0PJ9UJhWb2XisCaz6y6QcTh4gQnvHzgmEmK31GwiKnmBSEQuj8P5NGCO8RlN3cq3zpRpMDEoBRCjQYicllf/5P43r5OGvS1LhTiAMfyqE37URezNQa7aozBpH1GhIwAmjAtm84jXQjxUgZPYC0aSLuADYErScOP4792r6koH9t/DM5/M+jG2c4PNWynDczUw6Eaxl5E3hU0Ee9UN0Oee7iBnVenS/QMeZNyo5lMA/HXT5lrYiJGTYM0shRjGXXYBbJZhWerguSWDAdUd1gvuGP1nb7/+/Cvb46+HX7zYouS5Ojo0yPzMZ07X142jnKAfx9LnKdMUCwBJzbtoJ91Zc= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: result.changed or result.failed
- name: Host host1... present with empty sshpubkey list
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
sshpubkey: []
register: result
failed_when: not result.changed or result.failed
- name: Host host1... present with empty sshpubkey list
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
sshpubkey: []
register: result
failed_when: result.changed or result.failed
- name: Host host1... present with two sshpubkeys
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
sshpubkey:
# yamllint disable-line rule:line-length
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqmVDpEX5gnSjKuv97AyzOhaUMMKz8ahOA3GY77tVC4o68KNgMCmDSEG1/kOIaElngNLaCha3p/2iAcU9Bi1tLKUlm2bbO5NHNwHfRxY/3cJtq+/7D1vxJzqThYwI4F9vr1WxyY2+mMTv3pXbfAJoR8Mu06XaEY5PDetlDKjHLuNWF+/O7ZU8PsULTa1dJZFrtXeFpmUoLoGxQBvlrlcPI1zDciCSU24t27Zan5Py2l5QchyI7yhCyMM77KDtj5+AFVpmkb9+zq50rYJAyFVeyUvwjzErvQrKJzYpA0NyBp7vskWbt36M16/M/LxEK7HA6mkcakO3ESWx5MT1LAjvdlnxbWG3787MxweHXuB8CZU+9bZPFBaJ+VQtOfJ7I8eH0S16moPC4ak8FlcFvOH8ERDPWLFDqfy09yaZ7bVIF0//5ZI7Nf3YDe3S7GrBX5ieYuECyP6UNkTx9BRsAQeVvXEc6otzB7iCSnYBMGUGzCqeigoAWaVQUONsSR3Uatks= pinky@ipaserver.el81.local # noqa 204
# yamllint disable-line rule:line-length
- AAAAB3NzaC1yc2EAAAADAQABAAABgQDc8MIjaSrxLYHvu+hduoF4m6NUFSlXZWzYbd3BK4L47/U4eiXoOS6dcfuZJDjmLfOipc7XVp7NADwAgA1yBOAjbeVpXr2tC8w8saZibl75WBOEjDfNroiOh/f/ojrwwHg05QTVSZHs27sU1HBPyCQM/FHVM6EnRfmyiBkEBA/3ca0PJ9UJhWb2XisCaz6y6QcTh4gQnvHzgmEmK31GwiKnmBSEQuj8P5NGCO8RlN3cq3zpRpMDEoBRCjQYicllf/5P43r5OGvS1LhTiAMfyqE37URezNQa7aozBpH1GhIwAmjAtm84jXQjxUgZPYC0aSLuADYErScOP4792r6koH9t/DM5/M+jG2c4PNWynDczUw6Eaxl5E3hU0Ee9UN0Oee7iBnVenS/QMeZNyo5lMA/HXT5lrYiJGTYM0shRjGXXYBbJZhWerguSWDAdUd1gvuGP1nb7/+/Cvb46+HX7zYouS5Ojo0yPzMZ07X142jnKAfx9LnKdMUCwBJzbtoJ91Zc= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: not result.changed or result.failed
- name: Host host1... present with empty sshpubkey list
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host1_fqdn }}"
sshpubkey: []
register: result
failed_when: not result.changed or result.failed
- name: Host host1... absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
state: absent
ansible-freeipa-master/tests/host/test_hosts.yml 0000664 0000000 0000000 00000006400 14600563364 0022445 0 ustar 00root root 0000000 0000000 ---
- name: Test hosts
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host6_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
host3_fqdn: "{{ 'host3.' + ipaserver_domain }}"
host4_fqdn: "{{ 'host4.' + ipaserver_domain }}"
host5_fqdn: "{{ 'host5.' + ipaserver_domain }}"
host6_fqdn: "{{ 'host6.' + ipaserver_domain }}"
- name: Host host1..host6 absent
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
- name: "{{ host2_fqdn }}"
- name: "{{ host3_fqdn }}"
- name: "{{ host4_fqdn }}"
- name: "{{ host5_fqdn }}"
- name: "{{ host6_fqdn }}"
state: absent
- name: Hosts host1..host6 present
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
force: yes
- name: "{{ host2_fqdn }}"
force: yes
- name: "{{ host3_fqdn }}"
force: yes
- name: "{{ host4_fqdn }}"
force: yes
- name: "{{ host5_fqdn }}"
force: yes
- name: "{{ host6_fqdn }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Hosts host1..host6 present again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
force: yes
- name: "{{ host2_fqdn }}"
force: yes
- name: "{{ host3_fqdn }}"
force: yes
- name: "{{ host4_fqdn }}"
force: yes
- name: "{{ host5_fqdn }}"
force: yes
- name: "{{ host6_fqdn }}"
force: yes
register: result
failed_when: result.changed or result.failed
- name: Hosts host1..host6 absent
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
- name: "{{ host2_fqdn }}"
- name: "{{ host3_fqdn }}"
- name: "{{ host4_fqdn }}"
- name: "{{ host5_fqdn }}"
- name: "{{ host6_fqdn }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Hosts host1..host6 absent again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
- name: "{{ host2_fqdn }}"
- name: "{{ host3_fqdn }}"
- name: "{{ host4_fqdn }}"
- name: "{{ host5_fqdn }}"
- name: "{{ host6_fqdn }}"
state: absent
register: result
failed_when: result.changed or result.failed
# Use failed_when: not result.failed as this test needs to fail because a
# host is added two times in the same task
- name: Duplicate names in hosts failure test
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
force: yes
- name: "{{ host2_fqdn }}"
force: yes
- name: "{{ host3_fqdn }}"
force: yes
- name: "{{ host3_fqdn }}"
force: yes
register: result
failed_when: result.changed or not result.failed or "is used more than once" not in result.msg
ansible-freeipa-master/tests/host/test_hosts_managedby_host.yml 0000664 0000000 0000000 00000011706 14600563364 0025516 0 ustar 00root root 0000000 0000000 ---
- name: Test hosts managedby_host
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host5_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
host3_fqdn: "{{ 'host3.' + ipaserver_domain }}"
host4_fqdn: "{{ 'host4.' + ipaserver_domain }}"
host5_fqdn: "{{ 'host5.' + ipaserver_domain }}"
- name: Host absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
- "{{ host3_fqdn }}"
- "{{ host4_fqdn }}"
- "{{ host5_fqdn }}"
update_dns: yes
state: absent
- name: Host "{{ host5_fqdn }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ host5_fqdn }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Hosts "{{ host1_fqdn }}" .. "{{ 'host5.' + ipaserver_domain }}" present and managed by "{{ 'host5.' + ipaserver_domain }}"
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
force: yes
- name: "{{ host2_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
force: yes
- name: "{{ host3_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
force: yes
- name: "{{ host4_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
force: yes
- name: "{{ host5_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Hosts "{{ host1_fqdn }}" .. "{{ 'host5.' + ipaserver_domain }}" present and managed by "{{ 'host5.' + ipaserver_domain }}" again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
force: yes
- name: "{{ host2_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
force: yes
- name: "{{ host3_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
force: yes
- name: "{{ host4_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
force: yes
- name: "{{ host5_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
force: yes
register: result
failed_when: result.changed or result.failed
- name: Hosts "{{ host1_fqdn }}" .. "{{ 'host5.' + ipaserver_domain }}" managed by "{{ 'host5.' + ipaserver_domain }}"
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
- name: "{{ host2_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
- name: "{{ host3_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
- name: "{{ host4_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
- name: "{{ host5_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Hosts "{{ host1_fqdn }}" .. "{{ 'host5.' + ipaserver_domain }}" not managed by "{{ 'host5.' + ipaserver_domain }}"
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
- name: "{{ host2_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
- name: "{{ host3_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
- name: "{{ host4_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
- name: "{{ host5_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Hosts "{{ host1_fqdn }}" .. "{{ 'host5.' + ipaserver_domain }}" not managed by "{{ 'host5.' + ipaserver_domain }}" again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
- name: "{{ host2_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
- name: "{{ host3_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
- name: "{{ host4_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
- name: "{{ host5_fqdn }}"
managedby_host: "{{ host5_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Hosts "{{ host1_fqdn }}" .. "{{ 'host5.' + ipaserver_domain }}" absent
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
- name: "{{ host2_fqdn }}"
- name: "{{ host3_fqdn }}"
- name: "{{ host4_fqdn }}"
- name: "{{ host5_fqdn }}"
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-master/tests/host/test_hosts_principal.yml 0000664 0000000 0000000 00000014262 14600563364 0024513 0 ustar 00root root 0000000 0000000 ---
- name: Test hosts principal
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Get Realm from server name
ansible.builtin.set_fact:
ipaserver_realm: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') | upper }}"
when: ipaserver_realm is not defined
- name: Set host1_fqdn .. host2_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
- name: Host host1... and host2... absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
update_dns: yes
state: absent
- name: Host hostX... present with principal host/testhostX... X=[1,2]
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
force: yes
- name: "{{ host2_fqdn }}"
principal:
- "{{ 'host/testhost2.' + ipaserver_domain + '@' + ipaserver_realm }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Host hostX... principal 'host/hostX... present (existing already) X=[1,2]
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/host1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- name: "{{ host2_fqdn }}"
principal:
- "{{ 'host/host2.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Host hostX... principal host/testhostX... present again X=[1,2]
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- name: "{{ host2_fqdn }}"
principal:
- "{{ 'host/testhost2.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Host hostX.. principal host/testhostX... absent X=[1,2]
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- name: "{{ host2_fqdn }}"
principal:
- "{{ 'host/testhost2.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Host hostX... principal host/testhostX... absent again X=[1,2]
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- name: "{{ host2_fqdn }}"
principal:
- "{{ 'host/testhost2.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Host hostX... principal host/testhostX... and host/myhostX... present X=[1,2]
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- "{{ 'host/myhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- name: "{{ host2_fqdn }}"
principal:
- "{{ 'host/testhost2.' + ipaserver_domain + '@' + ipaserver_realm }}"
- "{{ 'host/myhost2.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Host hostX... principal host/testhostX... and host/myhostX... present again X=[1,2]
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- "{{ 'host/myhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- name: "{{ host2_fqdn }}"
principal:
- "{{ 'host/testhost2.' + ipaserver_domain + '@' + ipaserver_realm }}"
- "{{ 'host/myhost2.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Host hostX... principal host/testhostX... and host/myhostX... absent X=[1,2]
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- "{{ 'host/myhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- name: "{{ host2_fqdn }}"
principal:
- "{{ 'host/testhost2.' + ipaserver_domain + '@' + ipaserver_realm }}"
- "{{ 'host/myhost2.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Host hostX... principal host/testhostX... and host/myhostX... absent again X=[1,2]
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ host1_fqdn }}"
principal:
- "{{ 'host/testhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- "{{ 'host/myhost1.' + ipaserver_domain + '@' + ipaserver_realm }}"
- name: "{{ host2_fqdn }}"
principal:
- "{{ 'host/testhost2.' + ipaserver_domain + '@' + ipaserver_realm }}"
- "{{ 'host/myhost2.' + ipaserver_domain + '@' + ipaserver_realm }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Hosts host1... and host2... absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
update_dns: yes
state: absent
ansible-freeipa-master/tests/hostgroup/ 0000775 0000000 0000000 00000000000 14600563364 0020600 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/hostgroup/test_hostgroup.yml 0000664 0000000 0000000 00000015041 14600563364 0024415 0 ustar 00root root 0000000 0000000 ---
- name: Test hostgroup
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: true
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Ensure host-group databases, mysql-server and oracle-server are absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- databases
- mysql-server
- oracle-server
state: absent
- name: Test hosts db1 and db2 absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ 'db1.' + ipaserver_domain }}"
- "{{ 'db2.' + ipaserver_domain }}"
state: absent
- name: Host "{{ 'db1.' + ipaserver_domain }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'db1.' + ipaserver_domain }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Host "{{ 'db2.' + ipaserver_domain }}" present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'db2.' + ipaserver_domain }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group mysql-server is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: mysql-server
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group mysql-server is present again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: mysql-server
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure host-group oracle-server is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: oracle-server
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group oracle-server is present again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: oracle-server
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure host-group databases is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: databases
state: present
host:
- "{{ 'db1.' + ipaserver_domain }}"
hostgroup:
- oracle-server
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group databases is present again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: databases
state: present
host:
- "{{ 'db1.' + ipaserver_domain }}"
hostgroup:
- oracle-server
register: result
failed_when: result.changed or result.failed
- name: Ensure host db2 is member of host-group databases
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: databases
state: present
host:
- "{{ 'db2.' + ipaserver_domain }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure host db2 is member of host-group databases again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: databases
state: present
host:
- "{{ 'db2.' + ipaserver_domain }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure hosts db1 and db2 (no FQDN) are member of host-group databases again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: databases
state: present
host:
- db1
- db2
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure host-group mysql-server is member of host-group databases
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: databases
state: present
hostgroup:
- mysql-server
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group mysql-server is member of host-group databases again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: databases
state: present
hostgroup:
- mysql-server
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure host-group oracle-server is member of host-group databases (again)
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: databases
state: present
hostgroup:
- oracle-server
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure host-group databases, mysql-server and oracle-server are absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- databases
- mysql-server
- oracle-server
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group databases, mysql-server and oracle-server are absent again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- databases
- mysql-server
- oracle-server
state: absent
register: result
failed_when: result.changed or result.failed
- name: Test hosts db1 and db2 absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ 'db1.' + ipaserver_domain }}"
- "{{ 'db2.' + ipaserver_domain }}"
state: absent
ansible-freeipa-master/tests/hostgroup/test_hostgroup_case_insensitive.yml 0000664 0000000 0000000 00000013601 14600563364 0030030 0 ustar 00root root 0000000 0000000 ---
- name: Test hostgroup members case insensitive
hosts: ipaserver
become: true
gather_facts: false
module_defaults:
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
vars:
# Hostnames are supposed to have first letter
# capitalized for this test.
test_hosts:
- Host1
- Host2
test_hostgroups:
- testhostgroup1
# TestHostgrop2 is meant to use CamelCase here.
- TestHostGroup2
tasks:
- name: Test in all supported versions of IPA
block:
# setup environment
- name: Ensure domain name is set
ansible.builtin.set_fact:
ipa_domain: "test.local"
when: ipa_domain is not defined
- name: Ensure hostgroup testhostgroup1 and testhostgroup2 are absent
ipahostgroup:
name: "{{ test_hostgroups }}"
state: absent
- name: Ensure test hosts are present
ipahost:
name: "{{ item }}.{{ ipa_domain }}"
force: true
loop: "{{ test_hosts }}"
- name: Ensure hostgroup testhostgroup2 is present
ipahostgroup:
name: testhostgroup2
# tests
- name: Hostgroup should not be renamed only due to case
ipahostgroup:
name: testhostgroup2
rename: testhostgroup2
state: renamed
register: result
failed_when: result.changed or result.failed
- name: Test hostgroup presence with single host and action hostgroup
vars:
test_cases:
- { id: 1, value: "{{ test_hosts[0] | lower }}", expected: true }
- { id: 2, value: "{{ test_hosts[0] | upper }}", expected: false }
- { id: 3, value: "{{ test_hosts[0] }}", expected: false }
block:
- name: "Ensure hostgroup testhostgroup with host 'host1'"
ipahostgroup:
name: testhostgroup1
host: "{{ item.value }}"
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "Test id: {{ item.id }}"
- name: Test hostgroup presence with multiple hosts and action hostgroup
vars:
test_cases:
- { id: 1, value: "{{ test_hosts | lower }}", expected: true }
- { id: 2, value: "{{ test_hosts | upper }}", expected: false }
- { id: 3, value: "{{ test_hosts }}", expected: false }
- { id: 4, value: "{{ test_hosts[1] }}", expected: true }
- { id: 5, value: "{{ test_hosts[1] | lower }}", expected: false }
- { id: 6, value: "{{ test_hosts[1] | upper }}", expected: false }
- { id: 7, value: "{{ test_hosts[0] }}", expected: true }
- { id: 8, value: "{{ test_hosts[0] | lower }}", expected: false }
- { id: 9, value: "{{ test_hosts[0] | upper }}", expected: false }
block:
- name: "Ensure hostgroup testhostgroup with host 'host1'"
ipahostgroup:
name: testhostgroup1
host: "{{ item.value }}"
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "Test id: {{ item.id }}"
- name: Test hostgroup with multiple hosts and action member
vars:
test_cases:
- { id: 1, value: "{{ test_hosts | lower }}", state: "absent", expected: true }
- { id: 2, value: "{{ test_hosts | upper }}", state: "absent", expected: false }
- { id: 3, value: "{{ test_hosts }}", state: "present", expected: true }
- { id: 4, value: "{{ test_hosts[1] }}", state: "absent", expected: true }
- { id: 5, value: "{{ test_hosts[1] | lower }}", state: "absent", expected: false }
- { id: 6, value: "{{ test_hosts[1] | upper }}", state: "absent", expected: false }
- { id: 7, value: "{{ test_hosts[0] | lower }}", state: "present", expected: false }
- { id: 8, value: "{{ test_hosts[0] }}", state: "present", expected: false }
- { id: 9, value: "{{ test_hosts[0] | upper }}", state: "present", expected: false }
- { id: 10, value: "{{ test_hosts | upper }}", state: "present", expected: true }
- { id: 11, value: "{{ test_hosts[1] }}", state: "present", expected: false }
- { id: 12, value: "{{ test_hosts[0] | lower }}", state: "present", expected: false }
- { id: 13, value: "{{ test_hosts[0] }}", state: "absent", expected: true }
- { id: 14, value: "{{ test_hosts[0] | lower }}", state: "absent", expected: false }
- { id: 15, value: "{{ test_hosts[0] | upper }}", state: "absent", expected: false }
block:
- name: "Ensure hostgroup testhostgroup with host 'host1'"
ipahostgroup:
name: testhostgroup1
host: "{{ item.value }}"
action: member
state: "{{ item.state }}"
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "Test id: {{ item.id }}"
always:
# cleanup
- name: Ensure hostgroup testhostgroup is absent
ipahostgroup:
name: "{{ test_hostgroups }}"
state: absent
- name: Ensure test hosts are absent
ipahost:
name: "{{ test_hosts | product([ipa_domain]) | map('join') | list }}"
state: absent
ansible-freeipa-master/tests/hostgroup/test_hostgroup_client_context.yml 0000664 0000000 0000000 00000002435 14600563364 0027522 0 ustar 00root root 0000000 0000000 ---
- name: Test hostgroup
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test hostgroup using client context, in client host.
ansible.builtin.import_playbook: test_hostgroup.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test hostgroup using client context, in server host.
ansible.builtin.import_playbook: test_hostgroup.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/hostgroup/test_hostgroup_membermanager.yml 0000664 0000000 0000000 00000017577 14600563364 0027317 0 ustar 00root root 0000000 0000000 ---
- name: Test hostgroup membermanagers
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Tests requiring IPA version 4.8.4+
when: ipa_version is version('4.8.4', '>=')
block:
- name: Ensure host-group testhostgroup is absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name:
- testhostgroup
state: absent
- name: Ensure user manangeruser1 and manageruser2 is absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: manageruser1,manageruser2,unknown_user
state: absent
- name: Ensure group managergroup1 and managergroup2 are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name: managergroup1,managergroup2
state: absent
- name: Ensure host-group testhostgroup is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name:
- testhostgroup
- name: Ensure user manageruser1 and manageruser2 are present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: manageruser1
first: manageruser1
last: Last1
- name: manageruser2
first: manageruser2
last: Last2
register: result
failed_when: not result.changed or result.failed
- name: Ensure managergroup1 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: managergroup1
register: result
failed_when: not result.changed or result.failed
- name: Ensure managergroup2 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: managergroup2
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager user1 is present for testhostgroup
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_user: manageruser1
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager user1 is present for testhostgroup again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_user: manageruser1
register: result
failed_when: result.changed or result.failed
- name: Ensure membermanager group1 is present for testhostgroup
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_group: managergroup1
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager group1 is present for testhostgroup again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_group: managergroup1
register: result
failed_when: result.changed or result.failed
- name: Ensure membermanager user2 and group2 members are present for testhostgroup
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_user: manageruser2
membermanager_group: managergroup2
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager user2 and group2 members are present for testhostgroup again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_user: manageruser2
membermanager_group: managergroup2
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure membermanager user and group members are present for testhostgroup again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_user: manageruser1,manageruser2
membermanager_group: managergroup1,managergroup2
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure membermanager user1 and group1 members are absent for testhostgroup
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_user: manageruser1
membermanager_group: managergroup1
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager user1 and group1 members are absent for testhostgroup again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_user: manageruser1
membermanager_group: managergroup1
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure membermanager user1 and group1 members are present for testhostgroup
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_user: manageruser1
membermanager_group: managergroup1
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager user1 and group1 members are present for testhostgroup again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_user: manageruser1
membermanager_group: managergroup1
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure membermanager user and group members are absent for testhostgroup
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_user: manageruser1,manageruser2
membermanager_group: managergroup1,managergroup2
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure membermanager user and group members are absent for testhostgroup again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_user: manageruser1,manageruser2
membermanager_group: managergroup1,managergroup2
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure user manangeruser1 and manageruser2 is absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: manageruser1,manageruser2
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure group managergroup1 and managergroup2 are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name: managergroup1,managergroup2
state: absent
register: result
failed_when: not result.changed or result.failed
# Do not add failed_when result.failed, as this test needs to fail
# due to using an unknown user
- name: Ensure unknown membermanager_user member failure
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: testhostgroup
membermanager_user: unknown_user
action: member
register: result
failed_when: result.changed or "no such entry" not in result.msg
- name: Ensure host-group testhostgroup is absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name:
- testhostgroup
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-master/tests/hostgroup/test_hostgroup_membermanager_case_insensitive.yml 0000664 0000000 0000000 00000015607 14600563364 0032722 0 ustar 00root root 0000000 0000000 ---
- name: Test hostgroup membermanagers
hosts: ipaserver
become: true
gather_facts: false
module_defaults:
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
tasks:
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Tests requiring IPA version 4.8.4+
when: ipa_version is version('4.8.4', '>=')
block:
# setup environment
- name: Ensure host-group testhostgroup is absent
ipahostgroup:
name: testhostgroup
state: absent
- name: Ensure user manageruser1 and manageruser2 are present
ipauser:
users:
- name: manageruser1
first: manageruser1
last: Last1
- name: manageruser2
first: manageruser2
last: Last2
- name: Ensure managergroup1 and managergroup2 are present
ipagroup:
groups:
- name: managergroup1
- name: managergroup2
# tests
- name: Ensure host-group testhostgroup is present
ipahostgroup:
name: testhostgroup
- name: Test membermanager_user parameter presence
vars:
test_cases:
- { id: 1, value: "{{ 'ManagerUser1' | lower }}", expected: true }
- { id: 2, value: "{{ 'ManagerUser1' | upper }}", expected: false }
- { id: 3, value: 'ManagerUser1', expected: false }
block:
- name: "Ensure membermanager_user 'manageruser1' is present for testhostgroup"
ipahostgroup:
name: testhostgroup
membermanager_user: "{{ item.value }}"
action: member
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "{{ item.value }}"
- name: Test membermanager_group parameter presence
vars:
test_cases:
- { id: 1, value: "{{ 'ManagerGroup1' | upper }}", expected: true }
- { id: 2, value: "{{ 'ManagerGroup1' | lower }}", expected: false }
- { id: 3, value: 'ManagerGroup1', expected: false }
block:
- name: "Ensure membermanager_group 'managergroup1' is present for testhostgroup"
ipahostgroup:
name: testhostgroup
membermanager_group: "{{ item.value }}"
action: member
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "{{ item.value }}"
- name: Test membermanager_group and membermanager_user parameters presence
vars:
test_cases:
- { id: 1, user: 'ManagerUser2', group: 'ManagerGroup2', expected: true }
- { id: 2, user: "{{ 'ManagerUser2' | upper }}", group: "{{ 'ManagerGroup2' | upper }}", expected: false }
- { id: 3, user: "{{ 'ManagerUser2' | lower }}", group: "{{ 'ManagerGroup2' | lower }}", expected: false }
block:
- name: "Ensure membermanager_group 'managergroup2' and membermanager_user 'manageruser2' are present for testhostgroup"
ipahostgroup:
name: testhostgroup
membermanager_group: "{{ item.group }}"
membermanager_user: "{{ item.user }}"
action: member
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "Test id: {{ item.id }}"
- name: Test membermanager_group parameter absence
vars:
test_cases:
- { id: 1, value: 'ManagerGroup1', expected: true }
- { id: 2, value: "{{ 'ManagerGroup1' | lower }}", expected: false }
- { id: 3, value: "{{ 'ManagerGroup1' | upper }}", expected: false }
block:
- name: "Ensure membermanager_group 'managergroup1' is absent for testhostgroup"
ipahostgroup:
name: testhostgroup
membermanager_group: "{{ item.value }}"
action: member
state: absent
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "{{ item.value }}"
- name: Test membermanager_user parameter absence
vars:
test_cases:
- { id: 1, value: 'ManagerUser1', expected: true }
- { id: 2, value: "{{ 'ManagerUser1' | lower }}", expected: false }
- { id: 3, value: "{{ 'ManagerUser1' | upper }}", expected: false }
block:
- name: "Ensure membermanager_user 'manageruser1' is absent for testhostgroup"
ipahostgroup:
name: testhostgroup
membermanager_user: "{{ item.value }}"
action: member
state: absent
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "{{ item.value }}"
- name: Test membermanager_group and membermanager_user parameters absence
vars:
test_cases:
- { id: 1, user: "{{ 'ManagerUser2' | lower }}", group: "{{ 'ManagerGroup2' | lower }}", expected: true }
- { id: 2, user: 'ManagerUser2', group: 'ManagerGroup2', expected: false }
- { id: 3, user: "{{ 'ManagerUser2' | upper }}", group: "{{ 'ManagerGroup2' | upper }}", expected: false }
block:
- name: "Ensure membermanager_user 'manageruser2' and membermanager_group 'managergroup2' are absent for testhostgroup"
ipahostgroup:
name: testhostgroup
membermanager_group: "{{ item.group }}"
membermanager_user: "{{ item.user }}"
action: member
state: absent
register: output
failed_when: output.changed != item.expected or output.failed
loop: "{{ test_cases }}"
loop_control:
label: "Test id: {{ item.id }}"
always:
# cleanup
- name: Ensure host-group testhostgroup is absent
ipahostgroup:
name: testhostgroup
state: absent
- name: Ensure user manangeruser1 and manageruser2 is absent
ipauser:
name: manageruser1,manageruser2
state: absent
- name: Ensure group managergroup1 and managergroup2 are absent
ipagroup:
name: managergroup1,managergroup2
state: absent
ansible-freeipa-master/tests/hostgroup/test_hostgroup_rename.yml 0000664 0000000 0000000 00000006653 14600563364 0025755 0 ustar 00root root 0000000 0000000 ---
- name: Test hostgroup
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Tests requiring IPA version 4.8.7+
when: ipa_version is version('4.8.7', '>=')
block:
- name: Ensure testing host-group are absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name:
- databases
- datalake
- inexistenthostgroup
state: absent
- name: Ensure host-group databases is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
state: present
register: result
failed_when: not result.changed or result.failed
- name: Rename host-group from `databases` to `datalake`
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
rename: datalake
state: renamed
register: result
failed_when: not result.changed or result.failed
- name: Ensure host-group database was already absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: database
state: absent
register: result
failed_when: result.changed or result.failed
- name: Rename host-group from `databases` to `datalake`, again
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
rename: datalake
state: renamed
register: result
failed_when: result.changed or result.failed
- name: Rename host-group with same name.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: datalake
rename: datalake
state: renamed
register: result
failed_when: result.changed or result.failed
- name: Ensure testing hostgroups do not exist.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: inexistenthostgroup,alsoinexistent
state: absent
- name: Rename inexistent host-group to an existing one.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: inexistenthostgroup
rename: datalake
state: renamed
register: result
failed_when: result.changed or result.failed
- name: Rename inexistent host-group to a non-existing one.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: inexistenthostgroup
rename: alsoinexistent
state: renamed
register: result
failed_when: not result.failed or "Attribute `rename` can not be used, unless hostgroup exists." not in result.msg
- name: Ensure host-group databases is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
state: present
- name: Rename host-group to an existing one.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
rename: datalake
state: renamed
register: result
failed_when: not result.failed or "This entry already exists" not in result.msg
- name: Ensure host-group databases and datalake are absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name:
- databases
- datalake
state: absent
ansible-freeipa-master/tests/idoverridegroup/ 0000775 0000000 0000000 00000000000 14600563364 0021757 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/idoverridegroup/test_idoverridegroup.yml 0000664 0000000 0000000 00000016650 14600563364 0026762 0 ustar 00root root 0000000 0000000 ---
- name: Test idoverridegroup
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: false
gather_facts: false
module_defaults:
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipaidview:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
tasks:
# CLEANUP TEST ITEMS
- name: Ensure test groups test_group1..3 do not exist
ipagroup:
name:
- test_group1
- test_group2
- test_group3
state: absent
- name: Ensure test groups test_group1..3 are absent in idview test_idview
ipaidoverridegroup:
idview: test_idview
anchor:
- test_group1
- test_group2
- test_group3
state: absent
- name: Ensure test idview test_idview does not exist
ipaidview:
name: test_idview
state: absent
# CREATE TEST ITEMS
- name: Ensure test group test_group1 exists
ipagroup:
name: test_group1
- name: Ensure test group test_group2 exists
ipagroup:
name: test_group2
- name: Ensure test group test_group3 exists
ipagroup:
name: test_group3
- name: Ensure test idview test_idview exists
ipaidview:
name: test_idview
# TESTS
- name: Ensure test group test_group1 is present in idview test_idview
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
register: result
failed_when: not result.changed or result.failed
- name: Ensure test group test_group1 is present in idview test_idview, again
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
register: result
failed_when: result.changed or result.failed
- name: Ensure test group test_group2 is present in idview test_idview
ipaidoverridegroup:
idview: test_idview
anchor: test_group2
register: result
failed_when: not result.changed or result.failed
- name: Ensure test group test_group2 is present in idview test_idview, again
ipaidoverridegroup:
idview: test_idview
anchor: test_group2
register: result
failed_when: result.changed or result.failed
- name: Ensure test group test_group3 is present in idview test_idview
ipaidoverridegroup:
idview: test_idview
anchor: test_group3
register: result
failed_when: not result.changed or result.failed
- name: Ensure test group test_group3 is present in idview test_idview, again
ipaidoverridegroup:
idview: test_idview
anchor: test_group3
register: result
failed_when: result.changed or result.failed
# description
- name: Ensure test group test_group1 is present in idview test_idview with description
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
description: "test_group1 description"
register: result
failed_when: not result.changed or result.failed
- name: Ensure test group test_group1 is present in idview test_idview with description, again
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
description: "test_group1 description"
register: result
failed_when: result.changed or result.failed
- name: Ensure test group test_group1 is present in idview test_idview without description
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
description: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure test group test_group1 is present in idview test_idview without description, again
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
description: ""
register: result
failed_when: result.changed or result.failed
# name
- name: Ensure test group test_group1 is present in idview test_idview with internal name test_123_group
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
name: test_123_group
register: result
failed_when: not result.changed or result.failed
- name: Ensure test group test_group1 is present in idview test_idview with internal name test_123_group, again
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
name: test_123_group
register: result
failed_when: result.changed or result.failed
- name: Ensure test group test_group1 is present in idview test_idview without internal name
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
name: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure test group test_group1 is present in idview test_idview without internal name, again
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
name: ""
register: result
failed_when: result.changed or result.failed
# gid
- name: Ensure test group test_group1 is present in idview test_idview with gid 20001
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
gid: 20001
register: result
failed_when: not result.changed or result.failed
- name: Ensure test group test_group1 is present in idview test_idview with gid 20001, again
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
gid: 20001
register: result
failed_when: result.changed or result.failed
- name: Ensure test group test_group1 is present in idview test_idview without gid
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
gid: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure test group test_group1 is present in idview test_idview without gid, again
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
gid: ""
register: result
failed_when: result.changed or result.failed
# no fallback_to_ldap tests
# absent
- name: Ensure test group test_group1 is absent in idview test_idview
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure test group test_group1 is absent in idview test_idview, again
ipaidoverridegroup:
idview: test_idview
anchor: test_group1
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure test groups test_group2,3 are absent in idview test_idview
ipaidoverridegroup:
idview: test_idview
anchor:
- test_group2
- test_group3
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure test groups test_group2,3 are absent in idview test_idview, again
ipaidoverridegroup:
idview: test_idview
anchor:
- test_group2
- test_group3
state: absent
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure test group test_group1 does not exist
ipagroup:
name: test_group1
state: absent
- name: Ensure test groups test_group1..3 are absent in idview test_idview
ipaidoverridegroup:
idview: test_idview
anchor:
- test_group1
- test_group2
- test_group3
state: absent
- name: Ensure test idview test_idview does not exist
ipaidview:
name: test_idview
state: absent
ansible-freeipa-master/tests/idoverridegroup/test_idoverridegroup_client_context.yml 0000664 0000000 0000000 00000002744 14600563364 0032063 0 ustar 00root root 0000000 0000000 ---
- name: Test idoverridegroup
hosts: ipaclients, ipaserver
# It is normally not needed to set "become" to "true" for a module test.
# Only set it to true if it is needed to execute commands as root.
become: false
# Enable "gather_facts" only if "ansible_facts" variable needs to be used.
gather_facts: false
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaidoverridegroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test idoverridegroup using client context, in client host.
import_playbook: test_idoverridegroup.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test idoverridegroup using client context, in server host.
import_playbook: test_idoverridegroup.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
ansible-freeipa-master/tests/idoverrideuser/ 0000775 0000000 0000000 00000000000 14600563364 0021601 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/idoverrideuser/test_idoverrideuser.yml 0000664 0000000 0000000 00000044142 14600563364 0026423 0 ustar 00root root 0000000 0000000 ---
- name: Test idoverrideuser
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: false
gather_facts: false
module_defaults:
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipaidview:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
tasks:
# CLEANUP TEST ITEMS
- name: Ensure test users test_user1..3 do not exist
ipauser:
name:
- test_user1
- test_user2
- test_user3
state: absent
- name: Ensure test users test_user1..3 are absent in idview test_idview
ipaidoverrideuser:
idview: test_idview
anchor:
- test_user1
- test_user2
- test_user3
state: absent
- name: Ensure test idview test_idview does not exist
ipaidview:
name: test_idview
state: absent
# CREATE TEST ITEMS
- name: Ensure test users test_user1..3 exist
ipauser:
users:
- name: test_user1
first: test
last: user1
- name: test_user2
first: test
last: user2
- name: test_user3
first: test
last: user3
- name: Ensure test idview test_idview exists
ipaidview:
name: test_idview
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
# TESTS
- name: Ensure test user test_user1 is present in idview test_idview
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user2 is present in idview test_idview
ipaidoverrideuser:
idview: test_idview
anchor: test_user2
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user2 is present in idview test_idview, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user2
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user3 is present in idview test_idview
ipaidoverrideuser:
idview: test_idview
anchor: test_user3
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user3 is present in idview test_idview, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user3
register: result
failed_when: result.changed or result.failed
# description
- name: Ensure test user test_user1 is present in idview test_idview with description
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
description: "test_user1 description"
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview with description, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
description: "test_user1 description"
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without description
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
description: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without description, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
description: ""
register: result
failed_when: result.changed or result.failed
# name
- name: Ensure test user test_user1 is present in idview test_idview with internal name test_123_user
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
name: test_123_user
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview with internal name test_123_user, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
name: test_123_user
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without internal name
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
name: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without internal name, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
name: ""
register: result
failed_when: result.changed or result.failed
# uid
- name: Ensure test user test_user1 is present in idview test_idview with uid 20001
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
uid: 20001
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview with uid 20001, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
uid: 20001
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without uid
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
uid: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without uid, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
uid: ""
register: result
failed_when: result.changed or result.failed
# gecos
- name: Ensure test user test_user1 is present in idview test_idview with gecos "Gecos Test"
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
gecos: Gecos Test öäüÇœß
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview with gecos "Gecos Test", again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
gecos: Gecos Test öäüÇœß
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without gecos
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
gecos: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without gecos, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
gecos: ""
register: result
failed_when: result.changed or result.failed
# gidnumber
- name: Ensure test user test_user1 is present in idview test_idview with gidnumber 20001
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
gidnumber: 20001
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview with gidnumber 20001, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
gidnumber: 20001
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without gidnumber
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
gidnumber: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without gidnumber, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
gidnumber: ""
register: result
failed_when: result.changed or result.failed
# homedir
- name: Ensure test user test_user1 is present in idview test_idview with homedir /Users
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
homedir: /Users
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview with homedir /Users, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
homedir: /Users
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without homedir
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
homedir: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without homedir, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
homedir: ""
register: result
failed_when: result.changed or result.failed
# shell
- name: Ensure test user test_user1 is present in idview test_idview with shell /bin/someshell
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
shell: /bin/someshell
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview with shell /bin/someshell, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
shell: /bin/someshell
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without shell
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
shell: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without shell, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
shell: ""
register: result
failed_when: result.changed or result.failed
# sshpubkey
- name: Ensure test user test_user1 is present in idview test_idview with sshpubkey
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
sshpubkey:
# yamllint disable-line rule:line-length
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqmVDpEX5gnSjKuv97AyzOhaUMMKz8ahOA3GY77tVC4o68KNgMCmDSEG1/kOIaElngNLaCha3p/2iAcU9Bi1tLKUlm2bbO5NHNwHfRxY/3cJtq+/7D1vxJzqThYwI4F9vr1WxyY2+mMTv3pXbfAJoR8Mu06XaEY5PDetlDKjHLuNWF+/O7ZU8PsULTa1dJZFrtXeFpmUoLoGxQBvlrlcPI1zDciCSU24t27Zan5Py2l5QchyI7yhCyMM77KDtj5+AFVpmkb9+zq50rYJAyFVeyUvwjzErvQrKJzYpA0NyBp7vskWbt36M16/M/LxEK7HA6mkcakO3ESWx5MT1LAjvdlnxbWG3787MxweHXuB8CZU+9bZPFBaJ+VQtOfJ7I8eH0S16moPC4ak8FlcFvOH8ERDPWLFDqfy09yaZ7bVIF0//5ZI7Nf3YDe3S7GrBX5ieYuECyP6UNkTx9BRsAQeVvXEc6otzB7iCSnYBMGUGzCqeigoAWaVQUONsSR3Uatks= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview with sshpubkey, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
sshpubkey:
# yamllint disable-line rule:line-length
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqmVDpEX5gnSjKuv97AyzOhaUMMKz8ahOA3GY77tVC4o68KNgMCmDSEG1/kOIaElngNLaCha3p/2iAcU9Bi1tLKUlm2bbO5NHNwHfRxY/3cJtq+/7D1vxJzqThYwI4F9vr1WxyY2+mMTv3pXbfAJoR8Mu06XaEY5PDetlDKjHLuNWF+/O7ZU8PsULTa1dJZFrtXeFpmUoLoGxQBvlrlcPI1zDciCSU24t27Zan5Py2l5QchyI7yhCyMM77KDtj5+AFVpmkb9+zq50rYJAyFVeyUvwjzErvQrKJzYpA0NyBp7vskWbt36M16/M/LxEK7HA6mkcakO3ESWx5MT1LAjvdlnxbWG3787MxweHXuB8CZU+9bZPFBaJ+VQtOfJ7I8eH0S16moPC4ak8FlcFvOH8ERDPWLFDqfy09yaZ7bVIF0//5ZI7Nf3YDe3S7GrBX5ieYuECyP6UNkTx9BRsAQeVvXEc6otzB7iCSnYBMGUGzCqeigoAWaVQUONsSR3Uatks= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without sshpubkey
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
sshpubkey: []
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without sshpubkey, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
sshpubkey: []
register: result
failed_when: result.changed or result.failed
# certificate
- name: Ensure test user test_user1 is present in idview test_idview with 1 certificate
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview with 1 certificate, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview with 1 certificate member
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview with 3 certificate members
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview with 3 certificate members, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without certificate members
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
certificate:
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without certificate members, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
certificate:
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without certificates
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
certificate: []
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without certificates, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
certificate: []
register: result
failed_when: result.changed or result.failed
- name: Ensure test user test_user1 is present in idview test_idview without certificate members
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
# no fallback_to_ldap tests
# absent
- name: Ensure test user test_user1 is absent in idview test_idview
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure test user test_user1 is absent in idview test_idview, again
ipaidoverrideuser:
idview: test_idview
anchor: test_user1
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure test users test_user2,3 are absent in idview test_idview
ipaidoverrideuser:
idview: test_idview
anchor:
- test_user2
- test_user3
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure test users test_user2,3 are absent in idview test_idview, again
ipaidoverrideuser:
idview: test_idview
anchor:
- test_user2
- test_user3
state: absent
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure test user test_user1 does not exist
ipauser:
name: test_user1
state: absent
- name: Ensure test users test_user1..3 are absent in idview test_idview
ipaidoverrideuser:
idview: test_idview
anchor:
- test_user1
- test_user2
- test_user3
state: absent
- name: Ensure test idview test_idview does not exist
ipaidview:
name: test_idview
state: absent
- name: Remove certificate files.
ansible.builtin.shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/idoverrideuser/test_idoverrideuser_client_context.yml 0000664 0000000 0000000 00000002736 14600563364 0031530 0 ustar 00root root 0000000 0000000 ---
- name: Test idoverrideuser
hosts: ipaclients, ipaserver
# It is normally not needed to set "become" to "true" for a module test.
# Only set it to true if it is needed to execute commands as root.
become: false
# Enable "gather_facts" only if "ansible_facts" variable needs to be used.
gather_facts: false
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaidoverrideuser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test idoverrideuser using client context, in client host.
import_playbook: test_idoverrideuser.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test idoverrideuser using client context, in server host.
import_playbook: test_idoverrideuser.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
ansible-freeipa-master/tests/idp/ 0000775 0000000 0000000 00000000000 14600563364 0017322 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/idp/test_idp.yml 0000664 0000000 0000000 00000022463 14600563364 0021667 0 ustar 00root root 0000000 0000000 ---
- name: Test idp
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: false
gather_facts: false
module_defaults:
ipaidp:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
tasks:
# CHECK IF WE HAVE IDP SUPPORT
- name: Verify if ipd management is supported
ansible.builtin.shell:
cmd: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
RESULT=$(KRB5CCNAME={{ krb5ccname }} ipa command-show idp_add)
kdestroy -A -c {{ krb5ccname }}
echo $RESULT
vars:
krb5ccname: "__check_command_idp_add__"
register: check_command_idp_add
- name: Run tests for idp
when: not "idp_add" in check_command_idp_add.stderr
block:
# CLEANUP TEST ITEMS
- name: Ensure idps my-keycloak-idp, my-github-idp and my-google-idp are absent
ipaidp:
name:
- my-keycloak-idp
- my-github-idp
- my-google-idp
delete_continue: true
state: absent
# CREATE TEST ITEMS
# TESTS
- name: Ensure keycloak idp my-keycloak-idp is present
ipaidp:
name: my-keycloak-idp
provider: keycloak
organization: main
base_url: keycloak.idm.example.com:8443/auth
client_id: my-client-id
register: result
failed_when: not result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp is present, again
ipaidp:
name: my-keycloak-idp
provider: keycloak
organization: main
base_url: keycloak.idm.example.com:8443/auth
client_id: my-client-id
register: result
failed_when: result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp is present with all params
ipaidp:
name: my-keycloak-idp
organization: main
base_url: https://keycloak.idm.example.com:8443/auth
keys_uri: https://keycloak.idm.example.com:8443/certs
issuer_url: https://keycloak.idm.example.com:8443/issuer
secret: secret
scope: https://keycloak.idm.example.com:8443/scope
idp_user_id: testuser
client_id: my-client-id
register: result
failed_when: not result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp is present with all params, again
ipaidp:
name: my-keycloak-idp
organization: main
base_url: https://keycloak.idm.example.com:8443/auth
keys_uri: https://keycloak.idm.example.com:8443/certs
issuer_url: https://keycloak.idm.example.com:8443/issuer
secret: secret
scope: https://keycloak.idm.example.com:8443/scope
idp_user_id: testuser
client_id: my-client-id
register: result
# failed_when: result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp auth_uri is empty
ipaidp:
name: my-keycloak-idp
auth_uri: ""
client_id: my-client-id
register: result
failed_when: not result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp auth_uri is empty, again
ipaidp:
name: my-keycloak-idp
auth_uri: ""
client_id: my-client-id
register: result
failed_when: result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp dev_auth_uri is empty
ipaidp:
name: my-keycloak-idp
dev_auth_uri: ""
client_id: my-client-id
register: result
failed_when: not result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp dev_auth_uri is empty, again
ipaidp:
name: my-keycloak-idp
dev_auth_uri: ""
client_id: my-client-id
register: result
failed_when: result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp token_uri is empty
ipaidp:
name: my-keycloak-idp
token_uri: ""
client_id: my-client-id
register: result
failed_when: not result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp token_uri is empty, again
ipaidp:
name: my-keycloak-idp
token_uri: ""
client_id: my-client-id
register: result
failed_when: result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp userinfo_uri is empty
ipaidp:
name: my-keycloak-idp
userinfo_uri: ""
client_id: my-client-id
register: result
failed_when: not result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp userinfo_uri is empty, again
ipaidp:
name: my-keycloak-idp
userinfo_uri: ""
client_id: my-client-id
register: result
failed_when: result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp keys_uri is empty
ipaidp:
name: my-keycloak-idp
keys_uri: ""
client_id: my-client-id
register: result
failed_when: not result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp keys_uri is empty, again
ipaidp:
name: my-keycloak-idp
keys_uri: ""
client_id: my-client-id
register: result
failed_when: result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp issuer_url is empty
ipaidp:
name: my-keycloak-idp
issuer_url: ""
client_id: my-client-id
register: result
failed_when: not result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp issuer_url is empty, again
ipaidp:
name: my-keycloak-idp
issuer_url: ""
client_id: my-client-id
register: result
failed_when: result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp scope is empty
ipaidp:
name: my-keycloak-idp
scope: ""
client_id: my-client-id
register: result
failed_when: not result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp scope is empty, again
ipaidp:
name: my-keycloak-idp
scope: ""
client_id: my-client-id
register: result
failed_when: result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp idp_user_id is empty
ipaidp:
name: my-keycloak-idp
idp_user_id: ""
client_id: my-client-id
register: result
failed_when: not result.changed or result.failed
- name: Ensure keycloak idp my-keycloak-idp idp_user_id is empty, again
ipaidp:
name: my-keycloak-idp
idp_user_id: ""
client_id: my-client-id
register: result
failed_when: result.changed or result.failed
- name: Ensure idp my-keycloak-idp is absent
ipaidp:
name: my-keycloak-idp
delete_continue: true
state: absent
- name: Ensure keycloak idp my-keycloak-idp is failing with missing parameters
ipaidp:
name: my-keycloak-idp
provider: keycloak
client_id: my-client-id
register: result
failed_when: result.changed or not result.failed or
" is missing" not in result.msg
- name: Ensure github idp my-github-idp is present
ipaidp:
name: my-github-idp
provider: github
client_id: my-github-client-id
register: result
failed_when: not result.changed or result.failed
- name: Ensure github idp my-github-idp is present, again
ipaidp:
name: my-github-idp
provider: github
client_id: my-github-client-id
register: result
failed_when: result.changed or result.failed
- name: Ensure google idp my-google-idp is present using provider defaults without specifying provider
ipaidp:
name: my-google-idp
auth_uri: https://accounts.google.com/o/oauth2/auth
dev_auth_uri: https://oauth2.googleapis.com/device/code
token_uri: https://oauth2.googleapis.com/token
keys_uri: https://www.googleapis.com/oauth2/v3/certs
userinfo_uri: https://openidconnect.googleapis.com/v1/userinfo
client_id: my-google-client-id
scope: "openid email"
idp_user_id: email
register: result
failed_when: not result.changed or result.failed
- name: Ensure google idp my-google-idp is present using provider defaults without specifying provider, again
ipaidp:
name: my-google-idp
auth_uri: https://accounts.google.com/o/oauth2/auth
dev_auth_uri: https://oauth2.googleapis.com/device/code
token_uri: https://oauth2.googleapis.com/token
keys_uri: https://www.googleapis.com/oauth2/v3/certs
userinfo_uri: https://openidconnect.googleapis.com/v1/userinfo
client_id: my-google-client-id
scope: "openid email"
idp_user_id: email
register: result
failed_when: result.changed or result.failed
- name: Ensure google idp my-google-idp is present without changes using provider
ipaidp:
name: my-google-idp
provider: google
client_id: my-google-client-id
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure idps my-keycloak-idp, my-github-idp and my-google-idp are absent
ipaidp:
name:
- my-keycloak-idp
- my-github-idp
- my-google-idp
delete_continue: true
state: absent
ansible-freeipa-master/tests/idp/test_idp_client_context.yml 0000664 0000000 0000000 00000002634 14600563364 0024767 0 ustar 00root root 0000000 0000000 ---
- name: Test idp
hosts: ipaclients, ipaserver
# It is normally not needed to set "become" to "true" for a module test.
# Only set it to true if it is needed to execute commands as root.
become: false
# Enable "gather_facts" only if "ansible_facts" variable needs to be used.
gather_facts: false
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaidp:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test idp using client context, in client host.
import_playbook: test_idp.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test idp using client context, in server host.
import_playbook: test_idp.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
ansible-freeipa-master/tests/idrange/ 0000775 0000000 0000000 00000000000 14600563364 0020157 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/idrange/tasks_remove_trust.yml 0000664 0000000 0000000 00000001304 14600563364 0024643 0 ustar 00root root 0000000 0000000 ---
- name: Ensure testing trust is absent
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
realm: "{{ adserver.domain }}"
state: absent
- name: Ensure testing idranges are absent
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ adserver.realm }}_id_range"
continue: yes
state: absent
- name: Remove dns forward zone
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ adserver.domain }}"
state: absent
when: trust_dnszone is defined and trust_dnszone.changed
ansible-freeipa-master/tests/idrange/tasks_set_trust.yml 0000664 0000000 0000000 00000002330 14600563364 0024141 0 ustar 00root root 0000000 0000000 ---
- name: Ensure DNS forward zone to Windows AD
ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ adserver.domain }}"
forwarders:
- ip_address: "{{ adserver.ip_address }}"
forwardpolicy: first
register: trust_dnszone
- name: Set trust to Widows AD
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
realm: "{{ adserver.domain }}"
admin: Administrator
password: "{{ adserver.password }}"
base_id: "{{ trust_base_id | default(omit) }}"
range_type: "{{ trust_range_type | default(omit) }}"
range_size: "{{ trust_range_size | default(omit) }}"
register: result
failed_when: result.failed
- name: Retrieve Domain Security Identifier
ansible.builtin.shell:
cmd: |
kinit -c test_krb5_cache admin <<< SomeADMINpassword > /dev/null
KRB5CCNAME=test_krb5_cache ipa trust-show {{ adserver.domain }} | sed -n "/Domain Security Identifier/s/ //gp" | cut -d":" -f2
kdestroy -c test_krb5_cache -A -q > /dev/null
register: getsid
no_log: yes
- name: Set ipa_domain_sid.
ansible.builtin.set_fact:
ipa_domain_sid: "{{ getsid.stdout }}"
ansible-freeipa-master/tests/idrange/test_idrange.yml 0000664 0000000 0000000 00000031505 14600563364 0023356 0 ustar 00root root 0000000 0000000 ---
- name: Test idrange
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
vars:
adserver:
domain: "{{ winserver_domain | default('windows.local')}}"
realm: "{{ winserver_realm | default(winserver_domain) | default('windows.local') | upper }}"
password: "{{ winserver_admin_password | default('SomeW1Npassword') }}"
ip_address: "{{ winserver_ip | default(omit) }}"
tasks:
# CLEANUP TEST ITEMS
- name: Remove test trust.
ansible.builtin.include_tasks: tasks_remove_trust.yml
when: trust_test_is_supported | default(false)
- name: Ensure testing idranges are absent
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ adserver.realm }}_id_range"
- local_id_range
- ad_id_range
- ad_posix_id_range
continue: yes
state: absent
# CREATE TEST ITEMS
# TESTS
# Test local idrange, only if ipa-adtrust-install was not executed.
- name: Test local idrange
block:
- name: Ensure idrange with minimal attributes is present
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: local_id_range
base_id: 150000000
range_size: 200000
register: result
failed_when:
not (result.failed or result.changed) or (result.failed and 'ipa-adtrust-install has already been run' not in result.msg)
- name: Ensure idrange with minimal attributes is present, again
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: local_id_range
base_id: 150000000
range_size: 200000
register: result
failed_when:
result.changed or (result.failed and 'ipa-adtrust-install has already been run' not in result.msg)
- name: Ensure idrange with minimal attributes is absent
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: local_id_range
state: absent
register: range_delete
failed_when: range_delete.failed or (result.changed and not range_delete.changed)
# Test local idrange, even after ipa-adtrust-install.
- name: Ensure local idrange is present
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: local_id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
secondary_rid_base: 200000000
register: result
failed_when: not result.changed or result.failed
- name: Ensure local idrange is present again
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: local_id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
secondary_rid_base: 200000000
register: result
failed_when: result.changed or result.failed
- name: Ensure local idrange is absent
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: local_id_range
state: absent
continue: no
register: result
failed_when: not result.changed or result.failed
- name: Ensure local idrange is absent again
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: local_id_range
state: absent
continue: no
register: result
failed_when: result.changed or result.failed
rescue:
- name: Ensure local idranges is absent
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: local_id_range
- name: Execute idrange tests if trust test environment is supported
when: trust_test_is_supported | default(false)
block:
# Create trust with range_type: ipa-ad-trust
- name: Create trust with range_type 'ipa-ad-trust'
ansible.builtin.include_tasks: tasks_set_trust.yml
vars:
trust_base_id: 10000000
trust_range_size: 200000
trust_range_type: ipa-ad-trust
# Can't use secondary_rid_base with dom_sid/dom_name
- name: Ensure AD-trust idrange is present
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
idrange_type: ipa-ad-trust
dom_sid: "{{ ipa_domain_sid }}"
auto_private_groups: "false"
register: result
failed_when: not result.changed or result.failed
- name: Ensure AD-trust idrange is present again
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
idrange_type: ipa-ad-trust
dom_sid: "{{ ipa_domain_sid }}"
auto_private_groups: "false"
register: result
failed_when: result.changed or result.failed
- name: Check if AD-trust idrange is present, uning domain name
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
idrange_type: ipa-ad-trust
dom_name: "{{ adserver.domain }}"
auto_private_groups: "false"
check_mode: true
register: result
failed_when: result.changed or result.failed
- name: Modify AD-trust idrange 'base_id'
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
base_id: 151230000
register: result
failed_when: not result.changed or result.failed
- name: Modify AD-trust idrange 'base_id', again
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
base_id: 151230000
register: result
failed_when: result.changed or result.failed
- name: Modify AD-trust idrange 'range_size'
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
range_size: 100000
register: result
failed_when: not result.changed or result.failed
- name: Modify AD-trust idrange 'rid_base'
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
rid_base: 12345678
register: result
failed_when: not result.changed or result.failed
- name: Modify AD-trust idrange 'auto_private_groups'
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
auto_private_groups: "hybrid"
register: result
failed_when: not result.changed or result.failed
# Remove trust and idrange
- name: Remove test trust.
ansible.builtin.include_tasks: tasks_remove_trust.yml
- name: Ensure AD-trust idrange is absent
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
state: absent
# Create trust with range_type: ipa-ad-trust-posix
- name: Create trust with range_type 'ipa-ad-trust'
ansible.builtin.include_tasks: tasks_set_trust.yml
vars:
trust_base_id: 10000000
trust_range_size: 200000
trust_range_type: ipa-ad-trust
- name: Ensure AD-trust idrange is present, with dom_name
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
base_id: 150000000
range_size: 200000
rid_base: 1000000
idrange_type: ipa-ad-trust
dom_name: "{{ adserver.domain }}"
auto_private_groups: "false"
register: result
failed_when: not result.changed or result.failed
# Remove trust and idrange
- name: Remove test trust.
ansible.builtin.include_tasks: tasks_remove_trust.yml
- name: Ensure AD-trust idrange is absent
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
state: absent
# Remove trust and idrange
- name: Remove test trust.
ansible.builtin.include_tasks: tasks_remove_trust.yml
- name: Ensure AD-trust idrange is absent
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_id_range
state: absent
# Create trust with range_type: ipa-ad-trust-posix
- name: Create trust with range_type 'ipa-ad-trust-posix'
ansible.builtin.include_tasks: tasks_set_trust.yml
vars:
trust_base_id: 10000000
trust_range_size: 2000000
trust_range_type: ipa-ad-trust-posix
# Can't use secondary_rid_base or rid_base with "ad-trust-posix"
- name: Ensure AD-trust-posix idrange is present
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_posix_id_range
base_id: 150000000
range_size: 200000
idrange_type: ipa-ad-trust-posix
dom_sid: "{{ ipa_domain_sid }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure AD-trust-posix idrange is present again
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_posix_id_range
base_id: 150000000
range_size: 200000
idrange_type: ipa-ad-trust-posix
dom_sid: "{{ ipa_domain_sid }}"
register: result
failed_when: result.changed or result.failed
- name: Check if AD-trust-posix idrange is present, using dom_name
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_posix_id_range
base_id: 150000000
range_size: 200000
idrange_type: ipa-ad-trust-posix
dom_name: "{{ adserver.domain }}"
check_mode: yes
register: result
failed_when: result.changed or result.failed
# Remove trust and idrange
- name: Remove test trust.
ansible.builtin.include_tasks: tasks_remove_trust.yml
- name: Ensure AD-trust idrange is absent
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_posix_id_range
state: absent
# Create trust with range_type: ipa-ad-trust-posix
- name: Create trust with range_type 'ipa-ad-trust-posix'
ansible.builtin.include_tasks: tasks_set_trust.yml
vars:
trust_base_id: 10000000
trust_range_size: 2000000
trust_range_type: ipa-ad-trust-posix
# Can't use secondary_rid_base or rid_base with "ad-trust-posix"
- name: Ensure AD-trust-posix idrange is present, with dom_name
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ad_posix_id_range
base_id: 150000000
range_size: 200000
idrange_type: ipa-ad-trust-posix
dom_name: "{{ adserver.domain }}"
register: result
failed_when: not result.changed or result.failed
always:
# CLEANUP TEST ITEMS
- name: Remove test trust.
ansible.builtin.include_tasks: tasks_remove_trust.yml
- name: Ensure testing idranges are absent
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ adserver.realm }}_id_range"
- local_id_range
- ad_id_range
- ad_posix_id_range
continue: yes
state: absent
ansible-freeipa-master/tests/idrange/test_idrange_client_context.yml 0000664 0000000 0000000 00000002510 14600563364 0026452 0 ustar 00root root 0000000 0000000 ---
- name: Test idrange
hosts: ipaclients, ipaserver
# Change "become" or "gather_facts" to "yes",
# if you test playbook requires any.
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaidrange:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test idrange using client context, in client host.
ansible.builtin.import_playbook: test_idrange.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test idrange using client context, in server host.
ansible.builtin.import_playbook: test_idrange.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
ansible-freeipa-master/tests/idview/ 0000775 0000000 0000000 00000000000 14600563364 0020035 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/idview/test_idview.yml 0000664 0000000 0000000 00000023310 14600563364 0023105 0 ustar 00root root 0000000 0000000 ---
- name: Test idview
hosts: "{{ ipa_test_host | default('ipaserver') }}"
# It is normally not needed to set "become" to "true" for a module test.
# Only set it to true if it is needed to execute commands as root.
become: false
# Enable "gather_facts" only if "ansible_facts" variable needs to be used.
gather_facts: false
module_defaults:
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
ipaidview:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
tasks:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host2_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
host3_fqdn: "{{ 'host3.' + ipaserver_domain }}"
# CLEANUP TEST ITEMS
- name: Hosts "{{ host1_fqdn }}" and "{{ host2_fqdn }}" are absent
ipahost:
hosts:
- name: "{{ host1_fqdn }}"
- name: "{{ host2_fqdn }}"
state: absent
- name: Ensure idview test1_idview, test2_idview and renamed_idview are absent
ipaidview:
name:
- test1_idview
- test2_idview
- renamed_idview
state: absent
# CREATE TEST ITEMS
- name: Hosts "{{ host1_fqdn }}" and "{{ host2_fqdn }}" are present
ipahost:
hosts:
- name: "{{ host1_fqdn }}"
force: true
- name: "{{ host2_fqdn }}"
force: true
register: result
failed_when: not result.changed or result.failed
# TESTS
- name: Ensure idview test1_idview is present
ipaidview:
name: test1_idview
register: result
failed_when: not result.changed or result.failed
- name: Ensure idview test1_idview is present again
ipaidview:
name: test1_idview
# Add needed parameters here
register: result
failed_when: result.changed or result.failed
- name: Ensure idview test2_idview is present
ipaidview:
name: test2_idview
register: result
failed_when: not result.changed or result.failed
- name: Ensure idview test2_idview is present again
ipaidview:
name: test2_idview
# Add needed parameters here
register: result
failed_when: result.changed or result.failed
- name: Rename test1_idview to renamed_idview
ipaidview:
name: test1_idview
rename: renamed_idview
state: renamed
register: result
failed_when: not result.changed or result.failed
# This task will fail as there is no idview to be renamed
- name: Rename test1_idview to renamed_idview, again
ipaidview:
name: test1_idview
rename: renamed_idview
state: renamed
register: result
failed_when: result.changed or (not result.failed and "No idview 'test1_idview'" not in result.msg)
- name: Rename renamed_idview back to to test1_idview
ipaidview:
name: renamed_idview
rename: test1_idview
state: renamed
register: result
failed_when: not result.changed or result.failed
- name: Ensure idview test1_idview is present with description
ipaidview:
name: test1_idview
description: "Test IDView"
register: result
failed_when: not result.changed or result.failed
- name: Ensure idview test1_idview is present with description, again
ipaidview:
name: test1_idview
description: "Test IDView"
register: result
failed_when: result.changed or result.failed
- name: Ensure idview test1_idview is present with empty description
ipaidview:
name: test1_idview
description: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure idview test1_idview is present with empty description, again
ipaidview:
name: test1_idview
description: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure idview test1_idview is present with domain reolution order "{{ ipaserver_domain }}"
ipaidview:
name: test1_idview
domain_resolution_order: "{{ ipaserver_domain }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure idview test1_idview is present with domain reolution order "{{ ipaserver_domain }}", again
ipaidview:
name: test1_idview
domain_resolution_order: "{{ ipaserver_domain }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure idview test1_idview is present with empty domain reolution order
ipaidview:
name: test1_idview
domain_resolution_order: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure idview test1_idview is present with empty domain reolution order, again
ipaidview:
name: test1_idview
domain_resolution_order: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure host "{{ host1_fqdn }}" is applied to idview test1_idview
ipaidview:
name: test1_idview
host:
- "{{ host1_fqdn }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure host "{{ host1_fqdn }}" is applied to idview test1_idview, again
ipaidview:
name: test1_idview
host:
- "{{ host1_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure invalid host "{{ host3_fqdn }}" fails to applied to idview test1_idview
ipaidview:
name: test1_idview
host:
- "{{ host3_fqdn }}"
action: member
register: result
failed_when: result.changed or not result.failed or
"Invalid host" not in result.msg or
host3_fqdn not in result.msg
- name: Ensure invalid host "{{ host3_fqdn }}" does not fail to unapply from idview test1_idview
ipaidview:
name: test1_idview
host:
- "{{ host3_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure host "{{ host2_fqdn }}" is applied to idview test1_idview
ipaidview:
name: test1_idview
host:
- "{{ host2_fqdn }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure host "{{ host2_fqdn }}" is applied to idview test1_idview, again
ipaidview:
name: test1_idview
host:
- "{{ host2_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure hosts "{{ host1_fqdn }}" and "{{ host1_fqdn }}" are applied to idview test1_idview
ipaidview:
name: test1_idview
host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure hosts "{{ host1_fqdn }}" and "{{ host1_fqdn }}" are not applied to idview test1_idview
ipaidview:
name: test1_idview
host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure hosts "{{ host1_fqdn }}" and "{{ host1_fqdn }}" are not applied to idview test1_idview, again
ipaidview:
name: test1_idview
host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure host "{{ host1_fqdn }}" is applied to idview test1_idview
ipaidview:
name: test1_idview
host:
- "{{ host1_fqdn }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure host "{{ host1_fqdn }}" is applied to idview test1_idview, again
ipaidview:
name: test1_idview
host:
- "{{ host1_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure host "{{ host1_fqdn }}" is applied to idview test2_idview
ipaidview:
name: test2_idview
host:
- "{{ host1_fqdn }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure host "{{ host1_fqdn }}" is applied to idview test2_idview, again
ipaidview:
name: test2_idview
host:
- "{{ host1_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure host "{{ host1_fqdn }}" is not applied to idview test1_idview anymore
ipaidview:
name: test1_idview
host:
- "{{ host1_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure host "{{ host1_fqdn }}" is not applied to idview test2_idview
ipaidview:
name: test2_idview
host:
- "{{ host1_fqdn }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure host "{{ host1_fqdn }}" is not applied to idview test2_idview, again
ipaidview:
name: test2_idview
host:
- "{{ host1_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Hosts "{{ host1_fqdn }}" and "{{ host2_fqdn }}" absent
ipahost:
hosts:
- name: "{{ host1_fqdn }}"
- name: "{{ host2_fqdn }}"
state: absent
- name: Ensure idview test1_idview, test2_idview and renamed_idview are absent
ipaidview:
name:
- test1_idview
- test2_idview
- renamed_idview
state: absent
ansible-freeipa-master/tests/idview/test_idview_client_context.yml 0000664 0000000 0000000 00000002656 14600563364 0026221 0 ustar 00root root 0000000 0000000 ---
- name: Test idview
hosts: ipaclients, ipaserver
# It is normally not needed to set "become" to "true" for a module test.
# Only set it to true if it is needed to execute commands as root.
become: false
# Enable "gather_facts" only if "ansible_facts" variable needs to be used.
gather_facts: false
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaidview:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test idview using client context, in client host.
import_playbook: test_idview.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test idview using client context, in server host.
import_playbook: test_idview.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
ansible-freeipa-master/tests/location/ 0000775 0000000 0000000 00000000000 14600563364 0020356 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/location/test_location.yml 0000664 0000000 0000000 00000004475 14600563364 0023762 0 ustar 00root root 0000000 0000000 ---
- name: Test location
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
# CLEANUP TEST ITEMS
- name: Ensure location my_location1 is absent
ipalocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_location1
state: absent
# CREATE TEST ITEMS
# TESTS
- name: Ensure location my_location1 is present
ipalocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_location1
register: result
failed_when: not result.changed or result.failed
- name: Ensure location my_location1 is present again
ipalocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_location1
register: result
failed_when: result.changed or result.failed
- name: Ensure location my_location1 is present with description
ipalocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_location1
description: My Location 1
register: result
failed_when: not result.changed or result.failed
- name: Ensure location my_location1 is present again with description
ipalocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_location1
description: My Location 1
register: result
failed_when: result.changed or result.failed
- name: Ensure location my_location1 is absent
ipalocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_location1
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure location my_location1 is absent again
ipalocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_location1
state: absent
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure location my_location1 is absent
ipalocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_location1
state: absent
ansible-freeipa-master/tests/location/test_location_client_context.yml 0000664 0000000 0000000 00000002427 14600563364 0027057 0 ustar 00root root 0000000 0000000 ---
- name: Test location
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipalocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test location using client context, in client host.
ansible.builtin.import_playbook: test_location.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test location using client context, in server host.
ansible.builtin.import_playbook: test_location.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/netgroup/ 0000775 0000000 0000000 00000000000 14600563364 0020411 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/netgroup/test_netgroup.yml 0000664 0000000 0000000 00000013637 14600563364 0024050 0 ustar 00root root 0000000 0000000 ---
- name: Test netgroup
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
tasks:
- name: Test netgroup
block:
# CLEANUP TEST ITEMS
- name: Ensure netgroups are absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- my_netgroup1
- my_netgroup2
- my_netgroup3
state: absent
- name: Ensure hostgroup is absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- my_hostgroup1
state: absent
# CREATE TEST ITEMS
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Ensure netgroup my_netgroup2 is present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_netgroup2
- name: Ensure netgroup my_netgroup3 is present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_netgroup3
- name: Ensure hostgroup my_hostgroup1 is present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_hostgroup1
# TESTS
- name: Ensure netgroup my_netgroup1 is present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_netgroup1
register: result
failed_when: not result.changed or result.failed
- name: Ensure netgroup my_netgroup1 is present again
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_netgroup1
register: result
failed_when: result.changed or result.failed
- name: Ensure netgroup my_netgroup1 is present with description and
nisdomain
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_netgroup1
description: My netgroup 1
nisdomain: domain.test
register: result
failed_when: not result.changed or result.failed
- name: Ensure netgroup my_netgroup1 is present with new description
and new nisdomain
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_netgroup1
description: New description
nisdomain: new-domain.test
register: result
failed_when: not result.changed or result.failed
- name: Ensure netgroup my_netgroup1 is present with description and
nisdomain again
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_netgroup1
description: New description
nisdomain: new-domain.test
register: result
failed_when: result.changed or result.failed
- name: Ensure 2 netgroups aren't present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- my_netgroup1
- my_netgroup2
register: result
failed_when: result.changed or not result.failed or
"Only one netgroup can be added at a time." not in result.msg
- name: Ensure netgroup my_netgroup1 is absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_netgroup1
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure netgroup my_netgroup1 is absent again
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_netgroup1
state: absent
register: result
failed_when: result.changed or result.failed
# netgroup and hostgroup with the same name are deprecated (check hostgroup)
- name: Ensure hostgroup my_netgroup2 isn't present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_netgroup2
register: result
failed_when: result.changed or not result.failed or
"Hostgroups and netgroups share a common namespace" not in result.msg
# netgroup and hostgroup with the same name are deprecated (check netgroup)
- name: Ensure netgroup my_hostgroup1 isn't present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: my_hostgroup1
register: result
failed_when: result.changed or not result.failed or
"Hostgroups and netgroups share a common namespace" not in result.msg
- name: Ensure netgroups my_netgroup2, my_netgroup3 are absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- my_netgroup2
- my_netgroup3
state: absent
register: result
failed_when: not result.changed
always:
# cleanup
- name: Ensure netgroups are absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- my_netgroup1
- my_netgroup2
- my_netgroup3
state: absent
- name: Ensure hostgroups are absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- my_hostgroup1
state: absent
ansible-freeipa-master/tests/netgroup/test_netgroup_client_context.yml 0000664 0000000 0000000 00000003314 14600563364 0027141 0 ustar 00root root 0000000 0000000 ---
- name: Test netgroup
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test netgroup using client context, in client host.
ansible.builtin.import_playbook: test_netgroup.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test netgroup using client context, in server host.
ansible.builtin.import_playbook: test_netgroup.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
- name: Test netgroup with member using client context, in client host.
ansible.builtin.import_playbook: test_netgroup_member.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test netgroup with member using client context, in server host.
ansible.builtin.import_playbook: test_netgroup_member.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/netgroup/test_netgroup_member.yml 0000664 0000000 0000000 00000011455 14600563364 0025373 0 ustar 00root root 0000000 0000000 ---
- name: Netgroup member test
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
tasks:
- name: Test netgroup member
block:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host2_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
# CLEANUP TEST ITEMS
- name: Ensure users user1, user2 are absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: user1,user2
state: absent
- name: Ensure group group1 is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
state: absent
- name: Ensure hosts are absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
state: absent
- name: Ensure netgroups TestNetgroup1, admins are absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- TestNetgroup1
- admins
state: absent
# CREATE TEST ITEMS
- name: Ensure users user1, user2 are present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
users:
- name: user1
first: first1
last: last1
- name: user2
first: first2
last: last2
- name: Ensure groups group1 are present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
- name: Ensure hosts "{{ 'host[1..2].' + ipaserver_domain }}" are present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
hosts:
- name: "{{ host1_fqdn }}"
force: yes
- name: "{{ host2_fqdn }}"
force: yes
- name: Ensure netgroup admins is present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: admins
# TEST
- name: Ensure netgroup TestNetgroup1 is present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestNetgroup1
action: netgroup
description: Description for TestNetgroup1
nisdomain: "{{ ipaserver_domain }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure netgroup is present with members
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestNetgroup1
user: user1,user2
group: group1
host: "{{ host1_fqdn }}"
hostgroup: ipaservers
netgroup: admins
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure netgroup is present with members again (idempotence check)
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestNetgroup1
user: user1,user2
group: group1
host:
- "{{ host1_fqdn }}"
- host1
hostgroup: ipaservers
netgroup: admins
action: member
register: result
failed_when: result.changed or result.failed
always:
# CLEANUP TEST ITEMS
- name: Ensure users user1, user2 are absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: user1,user2
state: absent
- name: Ensure group group1 is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
state: absent
- name: Ensure hosts are absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
state: absent
- name: Ensure netgroups TestNetgroup1, admins are absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- TestNetgroup1
- admins
state: absent
ansible-freeipa-master/tests/netgroup/test_netgroup_member_absent.yml 0000664 0000000 0000000 00000014307 14600563364 0026726 0 ustar 00root root 0000000 0000000 ---
- name: Netgroup member absent test
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
tasks:
- name: Test netgroup member absent
block:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host2_fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
# CLEANUP TEST ITEMS
- name: Ensure users user1, user2 are absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: user1,user2
state: absent
- name: Ensure group group1 is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
state: absent
- name: Ensure hosts are absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
state: absent
- name: Ensure netgroups TestNetgroup1, admins are absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- TestNetgroup1
- admins
state: absent
# CREATE TEST ITEMS
- name: Ensure users user1, user2 are present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
users:
- name: user1
first: first1
last: last1
- name: user2
first: first2
last: last2
- name: Ensure group group1 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
- name: Ensure hosts "{{ 'host[1..2].' + ipaserver_domain }}" are present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
hosts:
- name: "{{ host1_fqdn }}"
force: yes
- name: "{{ host2_fqdn }}"
force: yes
- name: Ensure netgroup admins is present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: admins
- name: Ensure netgroup TestNetgroup1 is present
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestNetgroup1
description: Description for TestNetgroup1
nisdomain: "{{ ipaserver_domain }}"
- name: Ensure netgroup is present with members
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestNetgroup1
user: user1,user2
group: group1
host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
hostgroup: ipaservers
netgroup: admins
action: member
# TEST
- name: Ensure members are absent in netgroup
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestNetgroup1
user: user1
group: group1
host:
- "{{ host1_fqdn }}"
- host1
hostgroup: ipaservers
netgroup: admins
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure some members are still present in netgroup
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestNetgroup1
user: user2
host:
- "{{ host2_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure host was removed by hostname from netgroup
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestNetgroup1
host:
- host2
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure member user2 presents in netgroup
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: TestNetgroup1
user: user2
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure members from netgroups my_netgroup1,my_netgroup2 aren't
absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- my_netgroup1
- my_netgroup2
state: absent
action: member
register: result
failed_when: result.changed or not result.failed or
"Members can be removed only from one netgroup at a time." not in
result.msg
always:
# CLEANUP TEST ITEMS
- name: Ensure users user1, user2 are absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: user1,user2
state: absent
- name: Ensure group group1 is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
state: absent
- name: Ensure hosts are absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
state: absent
- name: Ensure netgroups TestNetgroup1, admins are absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- TestNetgroup1
- admins
state: absent
ansible-freeipa-master/tests/netgroup/test_netgroup_member_case_insensitive.yml 0000664 0000000 0000000 00000017240 14600563364 0031004 0 ustar 00root root 0000000 0000000 ---
- name: Test netgroup members should be case insensitive.
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
vars:
groups_present:
- eleMENT1
- Element2
- eLeMenT3
- ElemENT4
tasks:
- name: Test netgroup member case insensitive
block:
# SETUP
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Ensure test groups exist.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
loop: "{{ groups_present }}"
- name: Ensure test hostgroups exist.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: "hostgroup{{ item }}"
loop: "{{ groups_present }}"
- name: Ensure test netgroups exist.
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "netgroup{{ item }}"
loop: "{{ groups_present }}"
- name: Ensure test hosts exist.
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}.{{ ipaserver_domain }}"
force: yes
loop: "{{ groups_present }}"
- name: Ensure test users exist.
ipauser:
ipaadmin_password: SomeADMINpassword
name: "user{{ item }}"
first: "{{ item }}"
last: "{{ item }}"
loop: "{{ groups_present }}"
- name: Ensure netgroups don't exist
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
# TESTS
- name: Start tests.
ansible.builtin.debug:
msg: "Tests are starting."
- name: Ensure netgroups exist
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure netgroups exist with members
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "hostgroup{{ item }}"
host: "{{ item }}.{{ ipaserver_domain }}"
group: "{{ item }}"
user: "user{{ item }}"
netgroup: "netgroup{{ item }}"
action: member
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure netgroups exist with members, lowercase
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "hostgroup{{ item | lower }}"
host: "{{ item | lower }}.{{ ipaserver_domain }}"
group: "{{ item | lower }}"
user: "user{{ item | lower }}"
netgroup: "netgroup{{ item | lower }}"
action: member
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure netgroups exist with members, uppercase
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "hostgroup{{ item | upper }}"
host: "{{ item | upper }}.{{ ipaserver_domain }}"
group: "{{ item | upper }}"
user: "user{{ item | upper }}"
netgroup: "netgroup{{ item | upper }}"
action: member
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure netgroup member is absent
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "hostgroup{{ item }}"
host: "{{ item }}.{{ ipaserver_domain }}"
group: "{{ item }}"
user: "user{{ item }}"
netgroup: "netgroup{{ item }}"
action: member
state: absent
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure netgroup member is absent, lowercase
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "hostgroup{{ item | lower }}"
host: "{{ item | lower }}.{{ ipaserver_domain }}"
group: "{{ item | lower }}"
user: "user{{ item | lower }}"
netgroup: "netgroup{{ item | lower }}"
action: member
state: absent
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure netgroup member is absent, uppercase
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "hostgroup{{ item | upper }}"
host: "{{ item | upper }}.{{ ipaserver_domain }}"
group: "{{ item | upper }}"
user: "user{{ item | upper }}"
netgroup: "netgroup{{ item | upper }}"
action: member
state: absent
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure netgroup member is present, uppercase
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "hostgroup{{ item | upper }}"
host: "{{ item | upper }}.{{ ipaserver_domain }}"
group: "{{ item | upper }}"
user: "user{{ item | upper }}"
netgroup: "netgroup{{ item | upper }}"
action: member
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure netgroup member is present, lowercase
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "hostgroup{{ item | lower }}"
host: "{{ item | lower }}.{{ ipaserver_domain }}"
group: "{{ item | lower }}"
user: "user{{ item | lower }}"
netgroup: "netgroup{{ item | lower }}"
action: member
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure netgroup member is present, mixed case
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "hostgroup{{ item }}"
host: "{{ item }}.{{ ipaserver_domain }}"
group: "{{ item }}"
user: "user{{ item }}"
netgroup: "netgroup{{ item }}"
action: member
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: End tests.
ansible.builtin.debug:
msg: "All tests executed."
always:
# cleanup
- name: Ensure netgroups do not exist
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test groups do not exist.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test hostgroups do not exist.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: "hostgroup{{ item }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test netgroups do not exist.
ipanetgroup:
ipaadmin_password: SomeADMINpassword
name: "netgroup{{ item }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test hosts do not exist.
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}.{{ ipaserver_domain }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test users do not exist.
ipauser:
ipaadmin_password: SomeADMINpassword
name: "user{{ item }}"
state: absent
loop: "{{ groups_present }}"
ansible-freeipa-master/tests/permission/ 0000775 0000000 0000000 00000000000 14600563364 0020736 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/permission/test_permission.yml 0000664 0000000 0000000 00000031410 14600563364 0024707 0 ustar 00root root 0000000 0000000 ---
- name: Test permission
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
- name: Include task ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Ensure testing groups are present.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ item }}"
state: present
with_items:
- rbacgroup1
- rbacgroup2
# CLEANUP TEST ITEMS
- name: Ensure permission perm-test-1 is absent
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- perm-test-1
- perm-test-bindtype-test
- perm-test-renamed
state: absent
# TESTS
- name: Ensure permission perm-test-1 is present
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
object_type: host
memberof: rbacgroup1
filter: '(cn=*.ipa.*)'
right: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure permission perm-test-1 is present again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
object_type: host
memberof: rbacgroup1
filter: '(cn=*.ipa.*)'
right: all
register: result
failed_when: result.changed or result.failed
- name: Ensure permission perm-test-1 has an extra filter '(cn=*.internal.*)'
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
filter: '(cn=*.internal.*)'
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure permission perm-test-1 has an extra filter '(cn=*.internal.*)', again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
filter: '(cn=*.internal.*)'
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure permission perm-test-1 `right` has `write`
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
right: write
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure permission perm-test-1 `right` has `write`, again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
right: write
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure permission perm-test-1 `right` has no `write`
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
right: write
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure permission perm-test-1 `right` has no `write`, again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
right: write
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure permission perm-test-1 `memberof` has `rbackgroup2`
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
memberof: rbacgroup2
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure permission perm-test-1 `memberof` has `rbackgroup2`, again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
memberof: rbacgroup2
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure permission perm-test-1 `memberof` item `rbackgroup1` is absent
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
memberof: rbacgroup1
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure permission perm-test-1 `memberof` item `rbackgroup1` is absent, again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
memberof: rbacgroup1
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure permission perm-test-1 is present with attr carlicense
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
attrs:
- carlicense
register: result
failed_when: not result.changed or result.failed
- name: Ensure permission perm-test-1 is present with attr carlicense again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
attrs:
- carlicense
register: result
failed_when: result.changed or result.failed
- name: Ensure permission perm-test-1 is present with attr carlicense and displayname
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
attrs:
- carlicense
- displayname
register: result
failed_when: not result.changed or result.failed
- name: Ensure permission perm-test-1 is present with attr carlicense and displayname again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
attrs:
- carlicense
- displayname
register: result
failed_when: result.changed or result.failed
- name: Ensure attr gecos is present in permission perm-test-1
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
attrs:
- gecos
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure attr gecos is present in permission perm-test-1 again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
attrs:
- gecos
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure attr gecos is absent in permission perm-test-1
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
attrs:
- gecos
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure attr gecos is absent in permission perm-test-1 again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
attrs:
- gecos
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure attributes carlicense and displayname are present in permission "System{{ ':' }} Update DNS Entries"
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "System: Update DNS Entries"
attrs:
- carlicense
- displayname
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure attributes carlicense and displayname are present in permission "System{{ ':' }} Update DNS Entries" again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "System: Update DNS Entries"
attrs:
- carlicense
- displayname
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure attributes carlicense and displayname are present in permission "System{{ ':' }} Update DNS Entries"
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "System: Update DNS Entries"
attrs:
- carlicense
- displayname
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure attributes carlicense and displayname are present in permission "System{{ ':' }} Update DNS Entries" again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "System: Update DNS Entries"
attrs:
- carlicense
- displayname
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure permission perm-test-1 has rawfilter '(objectclass=ipagroup)'
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
rawfilter: '(objectclass=ipagroup)'
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure permission perm-test-1 has rawfilter '(objectclass=ipagroup)', again
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
rawfilter: '(objectclass=ipagroup)'
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure filter and rawfilter cannot be used together.
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
rawfilter: '(objectclass=ipagroup)'
filter: '(cn=*.internal.*)'
action: member
register: result
failed_when: not result.failed or "Cannot specify target filter and extra target filter simultaneously" not in result.msg
- name: Rename permission perm-test-1 to perm-test-renamed
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
rename: perm-test-renamed
state: renamed
register: result
failed_when: not result.changed or result.failed
- name: Ensure permission perm-test-1 is absent
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-1
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure permission perm-test-renamed is present
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-renamed
object_type: host
right: all
register: result
failed_when: result.changed or result.failed
- name: Ensure permission with bindtype 'self' is present, if IPA version >= 4.8.7
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-bindtype-test
bindtype: self
object_type: host
right: all
when: ipa_version is version('4.8.7', '>=')
register: result
failed_when: not result.changed or result.failed
- name: Fail to set permission perm-test-renamed bindtype to 'self', if IPA version < 4.8.7
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: perm-test-bindtype-test
bindtype: self
object_type: host
right: all
when: ipa_version is version('4.8.7', '<')
register: result
failed_when: not result.failed or "Bindtype 'self' is not supported by your IPA version." not in result.msg
# CLEANUP TEST ITEMS
- name: Ensure testing permissions are absent
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- perm-test-1
- perm-test-bindtype-test
- perm-test-renamed
state: absent
- name: Ensure testing groups are absent.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ item }}"
state: absent
with_items:
- rbacgroup1
- rbacgroup2
ansible-freeipa-master/tests/permission/test_permission_client_context.yml 0000664 0000000 0000000 00000002443 14600563364 0030015 0 ustar 00root root 0000000 0000000 ---
- name: Test permission
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipapermission:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test permission using client context, in client host.
ansible.builtin.import_playbook: test_permission.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test permission using client context, in server host.
ansible.builtin.import_playbook: test_permission.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/privilege/ 0000775 0000000 0000000 00000000000 14600563364 0020534 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/privilege/test_privilege.yml 0000664 0000000 0000000 00000017457 14600563364 0024322 0 ustar 00root root 0000000 0000000 ---
- name: Test privilege
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
# CLEANUP TEST ITEMS
- name: Ensure privilege "Broad Privilege" is absent
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- Broad Privilege
- DNS Privilege
state: absent
# CREATE TEST ITEMS
# TESTS
- name: Ensure privilege Broad Privilege is present
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
description: Broad Privilege
register: result
failed_when: not result.changed or result.failed
- name: Ensure privilege Broad Privilege is present again
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
description: Broad Privilege
register: result
failed_when: result.changed or result.failed
- name: Change privilege Broad Privilege description
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
description: Broad Privilege description
register: result
failed_when: not result.changed or result.failed
- name: Check if adding member permissions would cause a change (issue 669).
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
permission:
- "Write IPA Configuration"
- "System: Write DNS Configuration"
- "System: Update DNS Entries"
action: member
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure privilege Broad Privilege has permissions
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
permission:
- "Write IPA Configuration"
- "System: Write DNS Configuration"
- "System: Update DNS Entries"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure privilege Broad Privilege has permissions, again
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
permission:
- "Write IPA Configuration"
- "System: Write DNS Configuration"
- "System: Update DNS Entries"
action: member
register: result
failed_when: result.changed or result.failed
- name: Check if existing member permissions would not cause a change (issue 669).
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
permission:
- "Write IPA Configuration"
- "System: Write DNS Configuration"
- "System: Update DNS Entries"
action: member
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure privilege Broad Privilege member permission "Write IPA Configuration" is absent
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
permission:
- "Write IPA Configuration"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure privilege Broad Privilege member permission "Write IPA Configuration" is absent again
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
permission:
- "Write IPA Configuration"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure privilege Broad Privilege is absent
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure privilege Broad Privilege is present
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
register: result
failed_when: not result.changed or result.failed
- name: Ensure privilege Broad Privilege is renamed to "DNS Privilege"
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
rename: DNS Privilege
state: renamed
register: result
failed_when: not result.changed or result.failed
- name: Ensure privilege Broad Privilege cannot be renamed, because it does not exist.
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
rename: DNS Privilege
state: renamed
register: result
failed_when: not result.failed or "No privilege found to be renamed" not in result.msg
- name: Ensure privilege cannot be renamed to the same name.
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: DNS Privilege
rename: DNS Privilege
state: renamed
register: result
failed_when: result.changed or result.failed
- name: Ensure privilege cannot be renamed to the same name.
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: DNS Privilege
rename: DNS Privilege
state: renamed
register: result
failed_when: result.changed or result.failed
- name: Ensure "Broad Privilege" is absent.
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
state: absent
- name: Check if creating privilege Broad Privilege with permission would issue a change. (issue 669)
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
permission:
- "Write IPA Configuration"
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure privilege Broad Privilege is created with permission. (issue 529)
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
permission:
- "Write IPA Configuration"
register: result
failed_when: not result.changed or result.failed
- name: Ensure privilege Broad Privilege is created with permission, again. (issue 529)
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
permission:
- "Write IPA Configuration"
register: result
failed_when: result.changed or result.failed
- name: Check if exisintg privilege Broad Privilege with permission would not issue a change. (issue 669)
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: Broad Privilege
permission:
- "Write IPA Configuration"
check_mode: yes
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure privilege testing privileges are absent
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- Broad Privilege
- DNS Privilege
state: absent
ansible-freeipa-master/tests/privilege/test_privilege_client_context.yml 0000664 0000000 0000000 00000002435 14600563364 0027412 0 ustar 00root root 0000000 0000000 ---
- name: Test privilege
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaprivilege:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test privilege using client context, in client host.
ansible.builtin.import_playbook: test_privilege.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test privilege using client context, in server host.
ansible.builtin.import_playbook: test_privilege.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/pwpolicy/ 0000775 0000000 0000000 00000000000 14600563364 0020414 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/pwpolicy/test_pwpolicy.yml 0000664 0000000 0000000 00000026716 14600563364 0024060 0 ustar 00root root 0000000 0000000 ---
- name: Test pwpolicy
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
- name: Setup FreeIPA test facts.
ansible.builtin.import_tasks: ../env_freeipa_facts.yml
- name: Ensure maxlife of 90 for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxlife: 90
- name: Ensure absence of group ops
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
state: absent
- name: Ensure absence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
state: absent
- name: Ensure presence of group ops
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure presence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
minlife: 7
maxlife: 49
history: 5
priority: 1
lockouttime: 300
minlength: 8
minclasses: 5
maxfail: 3
failinterval: 5
register: result
failed_when: not result.changed or result.failed
- name: Ensure presence of pwpolicies for group ops again
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
minlife: 7
maxlife: 49
history: 5
priority: 1
lockouttime: 300
minlength: 8
minclasses: 5
maxfail: 3
failinterval: 5
register: result
failed_when: result.changed or result.failed
- name: Ensure maxlife of 49 for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxlife: 49
register: result
failed_when: not result.changed or result.failed
- name: Ensure maxlife of 49 for global_policy again
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxlife: 49
register: result
failed_when: result.changed or result.failed
- name: Ensure absence of pwpoliciy global_policy will fail
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
state: absent
register: result
failed_when: not result.failed or "'global_policy' can not be made absent." not in result.msg
- name: Ensure absence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure maxlife of 90 for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxlife: 90
register: result
failed_when: not result.changed or result.failed
- name: Ensure absence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure presence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
minlife: 7
maxlife: 49
history: 5
priority: 1
lockouttime: 300
minlength: 8
minclasses: 5
maxfail: 3
failinterval: 5
- name: Ensure policies are cleared
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
minlife: ""
maxlife: ""
history: ""
# priority: ""
lockouttime: ""
minclasses: ""
maxfail: ""
failinterval: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure policies are cleared, again
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
minlife: ""
maxlife: ""
history: ""
# priority: ""
lockouttime: ""
minclasses: ""
maxfail: ""
failinterval: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure minlength is not cleared due to FreeIPA issue
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
minlength: ""
register: result
failed_when:
(result.failed and not
("an internal error has occurred" in result.msg or
"int() argument must be" in result.msg))
or (not result.failed and not result.changed)
- name: Execute tests if ipa_version >= 4.9.0
when: ipa_version is version("4.9", ">=")
block:
- name: Ensure maxrepeat of 2 for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxrepeat: 2
register: result
failed_when: not result.changed or result.failed
- name: Ensure maxrepeat of 2 for global_policy, again
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxrepeat: 2
register: result
failed_when: result.changed or result.failed
- name: Ensure maxrepeat of 0 for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxrepeat: 0
register: result
failed_when: not result.changed or result.failed
- name: Ensure maxsequence of 4 for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxsequence: 4
register: result
failed_when: not result.changed or result.failed
- name: Ensure maxsequence of 4 for global_policy, again
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxsequence: 4
register: result
failed_when: result.changed or result.failed
- name: Ensure maxsequence of 0 for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxsequence: 0
register: result
failed_when: not result.changed or result.failed
- name: Ensure usercheck and dictcheck have known values
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
dictcheck: false
usercheck: false
- name: Ensure dictcheck is set for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
dictcheck: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure dictcheck is set for global_policy, again
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
dictcheck: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure dictcheck is not set for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
dictcheck: no
register: result
failed_when: not result.changed or result.failed
- name: Ensure usercheck is set for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
usercheck: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure usercheck is set for global_policy, again
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
usercheck: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure usercheck is not set for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
usercheck: no
register: result
failed_when: not result.changed or result.failed
- name: Ensure usercheck and dictcheck are cleared for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
dictcheck: ""
usercheck: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure usercheck and dictcheck are cleared for global_policy, again
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
dictcheck: ""
usercheck: ""
register: result
failed_when: result.changed or result.failed
- name: Execute tests if ipa_version >= 4.9.10
when: ipa_version is version("4.9.10", ">=")
block:
- name: Ensure grace limit is set to 10 for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
gracelimit: 10
register: result
failed_when: not result.changed or result.failed
- name: Ensure grace limit is set to 0 for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
gracelimit: 0
register: result
failed_when: not result.changed or result.failed
- name: Ensure grace limit is set to 0 for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
gracelimit: 0
register: result
failed_when: result.changed or result.failed
- name: Ensure grace limit is set to 0 for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
gracelimit: -1
register: result
failed_when: not result.changed or result.failed
- name: Ensure grace limit is cleared for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
gracelimit: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure grace limit is cleared for global_policy, again
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
gracelimit: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure grace limit is not set to -2 for global_policy
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
gracelimit: -2
register: result
failed_when: not result.failed and "must be at least -1" not in result.msg
ansible-freeipa-master/tests/pwpolicy/test_pwpolicy_client_context.yml 0000664 0000000 0000000 00000002427 14600563364 0027153 0 ustar 00root root 0000000 0000000 ---
- name: Test pwpolicy
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test pwpolicy using client context, in client host.
ansible.builtin.import_playbook: test_pwpolicy.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test pwpolicy using client context, in server host.
ansible.builtin.import_playbook: test_pwpolicy.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/pwpolicy/test_pwpolicy_invalid_data_type.yml 0000664 0000000 0000000 00000012132 14600563364 0027603 0 ustar 00root root 0000000 0000000 ---
- name: Test pwpolicy invalid data types
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
- name: Setup FreeIPA test facts.
ansible.builtin.import_tasks: ../env_freeipa_facts.yml
- name: Ensure presence of group ops
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
state: present
- name: Ensure invalid values raise proper error for argument minlife
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
minlife: "error"
register: result
failed_when: result.changed or (result.failed and "Invalid value 'error' for argument 'minlife'" not in result.msg)
- name: Ensure invalid values raise proper error for argument maxlife
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
maxlife: "error"
register: result
failed_when: result.changed or (result.failed and "Invalid value 'error' for argument 'maxlife'" not in result.msg)
- name: Ensure invalid values raise proper error for argument history
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
history: "error"
register: result
failed_when: result.changed or (result.failed and "Invalid value 'error' for argument 'history'" not in result.msg)
- name: Ensure invalid values raise proper error for argument priority
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
priority: "error"
register: result
failed_when: result.changed or (result.failed and "Invalid value 'error' for argument 'priority'" not in result.msg)
- name: Ensure invalid values raise proper error for argument lockouttime
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
lockouttime: "error"
register: result
failed_when: result.changed or (result.failed and "Invalid value 'error' for argument 'lockouttime'" not in result.msg)
- name: Ensure invalid values raise proper error for argument minlength
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
minlength: "error"
register: result
failed_when: result.changed or (result.failed and "Invalid value 'error' for argument 'minlength'" not in result.msg)
- name: Ensure invalid values raise proper error for argument minclasses
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
minclasses: "error"
register: result
failed_when: result.changed or (result.failed and "Invalid value 'error' for argument 'minclasses'" not in result.msg)
- name: Ensure invalid values raise proper error for argument maxfail
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
maxfail: "error"
register: result
failed_when: result.changed or (result.failed and "Invalid value 'error' for argument 'maxfail'" not in result.msg)
- name: Ensure invalid values raise proper error for argument failinterval
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
failinterval: "error"
register: result
failed_when: result.changed or (result.failed and "Invalid value 'error' for argument 'failinterval'" not in result.msg)
- name: Ensure invalid values for dictcheck raise proper error.
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
dictcheck: "error"
register: result
failed_when: result.changed or (result.failed and "is not a valid boolean" not in result.msg)
when: ipa_version is version("4.9", ">=")
- name: Ensure invalid values for usercheck raise proper error.
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
usercheck: "error"
register: result
failed_when: result.changed or (result.failed and "is not a valid boolean" not in result.msg)
when: ipa_version is version("4.9", ">=")
- name: Ensure invalid values for gracelimit raise proper error.
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
gracelimit: "error"
register: result
failed_when: result.changed or (result.failed and "Invalid value 'error' for argument 'gracelimit'" not in result.msg)
when: ipa_version is version("4.9.10", ">=")
- name: Ensure absence of group ops
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: ops
state: absent
ansible-freeipa-master/tests/pytests/ 0000775 0000000 0000000 00000000000 14600563364 0020261 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/pytests/conftest.py 0000664 0000000 0000000 00000003474 14600563364 0022470 0 ustar 00root root 0000000 0000000 # Authors:
# Sergio Oliveira Campos
#
# Copyright (C) 2020 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
import os
import yaml
def get_inventory(inventory_path):
with open(inventory_path) as inventory_yaml:
return yaml.safe_load(inventory_yaml)
def set_env_if_not_set(envvar, value):
if not os.getenv(envvar):
os.environ[envvar] = value
def pytest_configure(config): # pylint: disable=unused-argument
test_dir = os.getenv("TWD")
if not test_dir:
return
config_dir = os.path.join(test_dir, "config")
if os.path.exists(config_dir):
inventory_path = os.path.join(config_dir, "test.inventory.yml")
inventory = get_inventory(inventory_path)
print("Configuring execution using {0}".format(inventory_path))
ipaservers = inventory["all"]["children"]["ipaserver"]["hosts"]
ipaserver = list(ipaservers.values())[0]
private_key = os.path.join(config_dir, "id_rsa")
set_env_if_not_set("ANSIBLE_PRIVATE_KEY_FILE", private_key)
set_env_if_not_set("IPA_SERVER_HOST", ipaserver["ansible_host"])
set_env_if_not_set("ANSIBLE_REMOTE_USER", ipaserver["ansible_user"])
ansible-freeipa-master/tests/pytests/dnszone/ 0000775 0000000 0000000 00000000000 14600563364 0021741 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/pytests/dnszone/playbooks/ 0000775 0000000 0000000 00000000000 14600563364 0023744 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/pytests/dnszone/playbooks/dnszone_add_multiple_ipv4_ipv6_forwarders.yml0000664 0000000 0000000 00000000750 14600563364 0035040 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure the DNS zones is present with multiple forwarder ipv4, ipv6, and port.
hosts: ipaserver
tasks:
- name: Ensure DNS zone is present with multiple forwarders
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: 04testzone.test
forwarders:
- ip_address: 192.11.22.33
- ip_address: 192.11.22.34
port: 23
- ip_address: 2001:db8:cafe:1::1
- ip_address: 2001:db8:cafe:1::4
port: 34
ansible-freeipa-master/tests/pytests/dnszone/playbooks/dnszone_add_without_forwarder.yml 0000664 0000000 0000000 00000000424 14600563364 0032615 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure the DNS zones is present without forwarder as well.
hosts: ipaserver
tasks:
- name: Ensure DNS zone is present without forwarders
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: 01testzone.test
forwarders: []
ansible-freeipa-master/tests/pytests/dnszone/playbooks/dnszone_del_multiple.yml 0000664 0000000 0000000 00000000417 14600563364 0030710 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure remove multiple dnszone.
hosts: ipaserver
become: true
tasks:
- name: Ensure multiple DNS are absent
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: delzone1.com,delzone2.com,delzone3.com
state: absent
ansible-freeipa-master/tests/pytests/dnszone/playbooks/dnszone_disable.yml 0000664 0000000 0000000 00000000347 14600563364 0027636 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure the DNS zones disabled.
hosts: ipaserver
tasks:
- name: Ensure DNS zone is disabled
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: 26testzone.test
state: disabled
ansible-freeipa-master/tests/pytests/dnszone/playbooks/dnszone_enable.yml 0000664 0000000 0000000 00000000344 14600563364 0027456 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure the DNS zones enabled.
hosts: ipaserver
tasks:
- name: Ensure DNS zone is enabled
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: 26testzone.test
state: enabled
ansible-freeipa-master/tests/pytests/dnszone/playbooks/dnszone_invalid_ip.yml 0000664 0000000 0000000 00000000456 14600563364 0030352 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to with invalid IPs in allow_transfer.
hosts: ipaserver
become: true
tasks:
- name: Test adding a DNS zone with an invalid forwarder
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: invalidzone.test
forwarders:
- ip_address: in.va.li.d
ansible-freeipa-master/tests/pytests/dnszone/playbooks/dnszone_invalid_serial.yml 0000664 0000000 0000000 00000000473 14600563364 0031220 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure, not able to add invalid(more than 4294967295) serial numbers.
hosts: ipaserver
become: true
tasks:
- name: Test adding a DNS zone with an invalid serial
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: invalidserialzone.test
serial: 429496729599
ansible-freeipa-master/tests/pytests/dnszone/playbooks/dnszone_name_from_ip.yml 0000664 0000000 0000000 00000000404 14600563364 0030660 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure reverse zone is added by the IP..
hosts: ipaserver
tasks:
- name: Ensure a reverse DNS Zone with name inferred form an IP address
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 192.8.2.0/22
ansible-freeipa-master/tests/pytests/dnszone/playbooks/dnszone_with_forward_policy_only.yml 0000664 0000000 0000000 00000000441 14600563364 0033345 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure the DNS zones is present with forward_policy only.
hosts: ipaserver
tasks:
- name: Ensure DNS Zone is present with forward policy `only`
ipadnszone:
ipaadmin_password: SomeADMINpassword
name: 26testzone.test
forward_policy: only
ansible-freeipa-master/tests/pytests/dnszone/test_dnszone.py 0000664 0000000 0000000 00000012270 14600563364 0025034 0 ustar 00root root 0000000 0000000 # Authors:
# Sergio Oliveira Campos
#
# Copyright (C) 2020 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from pytest_sourceorder import ordered
from utils import AnsibleFreeIPATestCase, kinit_admin, kdestroy
BASE_PATH = "pytests/dnszone/playbooks/"
@ordered
class TestDNSZone(AnsibleFreeIPATestCase):
def test_dnszone_add_without_forwarder(self):
"""TC-01: Add dns zone without forwarder."""
zone01 = "01testzone.test"
self.check_notexists([zone01], "dnszone-find")
self.run_playbook(BASE_PATH + "dnszone_add_without_forwarder.yml")
self.check_details([zone01], "dnszone-find")
def test_dnszone_add_multiple_ipv4_ipv6_forwarders(self):
"""TC-04: Update multiple ipv4 and ipv6 forwarders."""
zone04 = "04testzone.test"
self.check_notexists([zone04], "dnszone-find")
# add dns zone with multiple forwarders
self.run_playbook(
(BASE_PATH + "dnszone_add_multiple_ipv4_ipv6_forwarders.yml")
)
exp_forwarders = [
"192.11.22.33",
"192.11.22.34 port 23",
"2001:db8:cafe:1::1",
"2001:db8:cafe:1::4 port 34",
]
exp_forwarders = ", ".join(exp_forwarders)
self.check_details([exp_forwarders], "dnszone-find", [zone04])
def test_dnszone_with_forward_policy_only(self):
"""TC-26: Add DNS zone with forward_policy only."""
zone26 = "26testzone.test"
self.check_notexists([zone26], "dnszone-find")
# add dns zone
self.run_playbook(BASE_PATH + "dnszone_with_forward_policy_only.yml")
self.check_details(["Forward policy: only"], "dnszone-find", [zone26])
def test_dnszone_disable(self):
"""TC-30: Disable DNS Zone."""
zone26 = "26testzone.test"
self.check_details(
["Active zone: (TRUE|True)"], "dnszone-find", [zone26]
)
# Disable dns zone
self.run_playbook(BASE_PATH + "dnszone_disable.yml")
self.check_details(
["Active zone: (FALSE|False)"], "dnszone-find", [zone26]
)
def test_dnszone_enable(self):
"""TC-31: Enable DNS Zone."""
zone26 = "26testzone.test"
self.check_details(
["Active zone: (FALSE|False)"], "dnszone-find", [zone26]
)
# Enable dns zone
self.run_playbook(BASE_PATH + "dnszone_enable.yml")
self.check_details(
["Active zone: (TRUE|True)"], "dnszone-find", [zone26]
)
def test_dnszone_name_from_ip(self):
"""TC-35: Add dns zone with reverse zone IP. Bug#1845056."""
zone = "8.192.in-addr.arpa."
expected_msg = "Zone name: {0}".format(zone)
self.check_notexists([expected_msg], "dnszone-find", [zone])
self.mark_xfail_using_ansible_freeipa_version(
version="ansible-freeipa-0.1.12-5.el8.noarch",
reason="Fix is not available for BZ-1845056",
)
self.run_playbook(BASE_PATH + "dnszone_name_from_ip.yml")
self.check_details([expected_msg], "dnszone-find", [zone])
def test_dnszone_del_multiple(self):
"""TC-33: Delete multiple DNS zones Bug#1845058."""
zone = ["delzone1.com", "delzone2.com", "delzone3.com"]
for add_zone in zone:
kinit_admin(self.master)
self.master.run("ipa dnszone-add " + add_zone)
self.check_details([add_zone], "dnszone-show", [add_zone])
kdestroy(self.master)
self.mark_xfail_using_ansible_freeipa_version(
version="ansible-freeipa-0.1.12-5.el8.noarch",
reason="Fix is not available for BZ-1845058",
)
self.run_playbook(BASE_PATH + "dnszone_del_multiple.yml")
# verify multiple dnszones are removed
for add_zone in zone:
error = "ipa: ERROR: {0}.: DNS zone not found".format(add_zone)
self.check_notexists([error], "dnszone-show", [add_zone])
def test_dnszone_invalid_ip(self):
"""TC-07: Update with invalid IPs in allow_transfer. Bug#1845051."""
invalid_zone_name = "invalidzone.test"
invalid_zone_ip = "in.va.li.d"
expected_error = "Invalid IP for DNS forwarder"
self.mark_xfail_using_ansible_freeipa_version(
version="ansible-freeipa-0.1.12-5.el8.noarch",
reason="Fix is not available for BZ-1845058",
)
self.run_playbook_with_exp_msg(
BASE_PATH + "dnszone_invalid_ip.yml", expected_error,
)
self.check_notexists(
[invalid_zone_ip], "dnszone-show", [invalid_zone_name],
)
ansible-freeipa-master/tests/role/ 0000775 0000000 0000000 00000000000 14600563364 0017507 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/role/env_cleanup.yml 0000664 0000000 0000000 00000002444 14600563364 0022535 0 ustar 00root root 0000000 0000000 ---
- name: Ensure test user is absent.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- user01
- user02
- user03
state: absent
- name: Ensure test group is absent.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- group01
- group02
state: absent
- name: Ensure test hostgroup is absent.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- hostgroup01
- hostgroup02
state: absent
- name: Ensure test host is absent.
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
state: absent
- name: Ensure test service is absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "service01/{{ host1_fqdn }}"
- "service02/{{ host2_fqdn }}"
state: absent
- name: Ensure test roles are absent.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- renamerole
- testrole
state: absent
ansible-freeipa-master/tests/role/env_facts.yml 0000664 0000000 0000000 00000001364 14600563364 0022206 0 ustar 00root root 0000000 0000000 ---
- name: Ensure ipaserver_domain is set
when: ipaserver_domain is not defined
block:
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: "'fqdn' in ansible_facts"
- name: Set Domain to 'ipa.test' if FQDN could not be retrieved.
ansible.builtin.set_fact:
ipaserver_domain: "ipa.test"
when: "'fqdn' not in ansible_facts"
- name: Set ipaserver_realm.
ansible.builtin.set_fact:
ipaserver_realm: "{{ ipaserver_domain | upper }}"
when: ipaserver_realm is not defined
- name: Create FQDN for host01
ansible.builtin.set_fact:
host1_fqdn: "host01.{{ ipaserver_domain }}"
host2_fqdn: "host02.{{ ipaserver_domain }}"
ansible-freeipa-master/tests/role/env_setup.yml 0000664 0000000 0000000 00000002631 14600563364 0022244 0 ustar 00root root 0000000 0000000 ---
- name: Cleanup environment.
ansible.builtin.import_tasks: env_cleanup.yml
- name: Ensure test user is present.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
users:
- name: user01
first: First
last: Last
- name: user02
first: First
last: Last
- name: user03
first: First
last: Last
- name: Ensure test group is present.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ item }}"
with_items:
- group01
- group02
- name: Ensure test host is present.
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ item }}"
force: yes
with_items:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
- name: Ensure test hostgroup is present.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ item[0] }}"
host:
- "{{ item[1] }}"
with_nested:
- [hostgroup01, hostgroup02]
- ["{{ host1_fqdn }}", "{{ host2_fqdn }}"]
- name: Ensure test service is present.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ item }}"
force: yes
with_items:
- "service01/{{ host1_fqdn }}"
- "service02/{{ host2_fqdn }}"
ansible-freeipa-master/tests/role/test_role.yml 0000664 0000000 0000000 00000027503 14600563364 0022241 0 ustar 00root root 0000000 0000000 ---
- name: Test role module
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: yes
gather_facts: yes
tasks:
- name: Set environment facts.
ansible.builtin.import_tasks: env_facts.yml
- name: Setup environment.
ansible.builtin.import_tasks: env_setup.yml
# tests
- name: Ensure role is present.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: renamerole
description: A role in IPA.
register: result
failed_when: not result.changed or result.failed
- name: Ensure role is present, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: renamerole
description: A role in IPA.
register: result
failed_when: result.changed or result.failed
- name: Rename role.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: renamerole
rename: testrole
state: renamed
register: result
failed_when: not result.changed or result.failed
# Do not test result.failed, this task will fail as there is no role to
# be renamed.
- name: Rename role, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: renamerole
rename: testrole
state: renamed
register: result
failed_when: result.changed or (not result.failed and "No role 'renamerole'" not in result.msg)
- name: Ensure role has member has privileges.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
privilege:
- DNS Servers
- Host Administrators
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has member has privileges, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
privilege:
- DNS Servers
- Host Administrators
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure role has less privileges.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
privilege:
- Host Administrators
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has less privileges, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
privilege:
- Host Administrators
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure role has member has privileges restored.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
privilege:
- DNS Servers
- Host Administrators
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has member has privileges restored, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
privilege:
- DNS Servers
- Host Administrators
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure role member privileges are absent.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
privilege:
- DNS Servers
- Host Administrators
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure role member privileges are absent, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
privilege:
- DNS Servers
- Host Administrators
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure invalid privileged is not assigned to role.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
privilege: Invalid Privilege
action: member
register: result
failed_when: not result.failed or "privilege not found" not in result.msg
- name: Ensure role has member user present.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
user:
- user01
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has member user present, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
user:
- user01
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure role has member user absent.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
user:
- user01
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has member user absent, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
user:
- user01
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure role has member group present.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
group:
- group01
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has member group present, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
group:
- group01
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure role has member group absent.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
group:
- group01
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has member group absent, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
group:
- group01
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure role has member host present.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
host:
- "{{ host1_fqdn }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has member host present, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
host:
- "{{ host1_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure role has member host absent.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
host:
- "{{ host1_fqdn }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has member host absent, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
host:
- "{{ host1_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure role has member hostgroup present.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
hostgroup:
- hostgroup01
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has member hostgroup present, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
hostgroup:
- hostgroup01
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure role has member hostgroup absent.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
hostgroup:
- hostgroup01
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has member hostgroup absent, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
hostgroup:
- hostgroup01
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure role is absent.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure role is absent, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure role with members is present.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
user:
- user01
group:
- group01
host:
- "{{ host1_fqdn }}"
hostgroup:
- hostgroup01
privilege:
- Group Administrators
- User Administrators
service:
- "service01/{{ host1_fqdn }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure role with members is present, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
user:
- user01
group:
- group01
host:
- "{{ host1_fqdn }}"
hostgroup:
- hostgroup01
privilege:
- Group Administrators
- User Administrators
service:
- "service01/{{ host1_fqdn }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure role is absent.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure role is absent, again.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrole
state: absent
register: result
failed_when: result.changed or result.failed
# cleanup
- name: Cleanup environment.
ansible.builtin.include_tasks: env_cleanup.yml
ansible-freeipa-master/tests/role/test_role_client_context.yml 0000664 0000000 0000000 00000002377 14600563364 0025345 0 ustar 00root root 0000000 0000000 ---
- name: Test role
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
iparole:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test role using client context, in client host.
ansible.builtin.import_playbook: test_role.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test role using client context, in server host.
ansible.builtin.import_playbook: test_role.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/role/test_role_lists_handling.yml 0000664 0000000 0000000 00000016764 14600563364 0025332 0 ustar 00root root 0000000 0000000 ---
- name: Test service member in role module.
hosts: ipaserver
become: yes
gather_facts: yes
tasks:
- name: Set environment facts.
ansible.builtin.import_tasks: env_facts.yml
- name: Setup environment.
ansible.builtin.import_tasks: env_setup.yml
- name: Add role.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user: user01
group: group01
hostgroup: hostgroup01
host: "{{ host1_fqdn }}"
service: "service01/{{ host1_fqdn }}"
privilege:
- Automember Readers
- ADTrust Agents
register: result
failed_when: result.failed or not result.changed
# Test fix for https://github.com/freeipa/ansible-freeipa/issues/409
- name: Add new privileges to role.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
privilege:
- DNS Servers
- Host Administrators
- DNS Administrators
- Group Administrators
action: member
register: result
failed_when: result.failed or not result.changed
- name: Verify role privileges.
ansible.builtin.shell:
cmd: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa role-show testrole
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: |
result.failed or not (
"Automember Readers" in result.stdout
and "ADTrust Agents" in result.stdout
and "DNS Servers" in result.stdout
and "Host Administrators" in result.stdout
and "DNS Administrators" in result.stdout
and "Group Administrators" in result.stdout
)
vars:
krb5ccname: verify_issue_409
# End of test fix for https://github.com/freeipa/ansible-freeipa/issues/409
# Test fix for https://github.com/freeipa/ansible-freeipa/issues/412
- name: Add new user to role.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user: user02
action: member
register: result
failed_when: result.failed or not result.changed
- name: Verify role users.
ansible.builtin.shell:
cmd: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa role-show testrole
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: |
result.failed or not (
"user01" in result.stdout
and "user02" in result.stdout
)
vars:
krb5ccname: verify_issue_412
- name: Add new group to role.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
group: group02
action: member
register: result
failed_when: result.failed or not result.changed
- name: Verify role group.
ansible.builtin.shell:
cmd: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa role-show testrole
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: |
result.failed or not (
"group01" in result.stdout
and "group02" in result.stdout
)
vars:
krb5ccname: verify_issue_412
- name: Add new host to role.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
host: "{{ host2_fqdn }}"
action: member
register: result
failed_when: result.failed or not result.changed
- name: Verify role hosts.
ansible.builtin.shell:
cmd: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa role-show testrole
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: |
result.failed or not (
host1 in result.stdout
and host2 in result.stdout
)
vars:
krb5ccname: verify_issue_412
host1: " {{ host1_fqdn }}"
host2: " {{ host2_fqdn }}"
- name: Add new hostgroup to role.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
hostgroup: hostgroup02
action: member
register: result
failed_when: result.failed or not result.changed
- name: Verify role hostgroups.
ansible.builtin.shell:
cmd: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa role-show testrole
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: |
result.failed or not (
" hostgroup01" in result.stdout
and " hostgroup02" in result.stdout
)
vars:
krb5ccname: verify_issue_412
- name: Add new service to role.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
service: "service02/{{ host2_fqdn }}"
action: member
register: result
failed_when: result.failed or not result.changed
- name: Verify role services.
ansible.builtin.shell:
cmd: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa role-show testrole
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: |
result.failed or not (
service1 in result.stdout
and service1 in result.stdout
)
vars:
krb5ccname: verify_issue_412
service1: "service01/{{ host1_fqdn }}"
service2: "service02/{{ host2_fqdn }}"
# End of test fix for https://github.com/freeipa/ansible-freeipa/issues/412
# Test fix for https://github.com/freeipa/ansible-freeipa/issues/413
- name: Add new user to role.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user: user03
action: member
register: result
failed_when: result.failed or not result.changed
- name: Verify role services.
ansible.builtin.shell:
cmd: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa role-show testrole
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: |
result.failed or not (
service1 in result.stdout
and service1 in result.stdout
and "user03" in result.stdout
)
vars:
krb5ccname: verify_issue_413
service1: "service01/{{ host1_fqdn }}"
service2: "service02/{{ host2_fqdn }}"
- name: Remove user from role.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user: user03
action: member
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Verify role services.
ansible.builtin.shell:
cmd: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa role-show testrole
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: |
result.failed or not (
service1 in result.stdout
and service1 in result.stdout
and "user03" not in result.stdout
)
vars:
krb5ccname: verify_issue_413
service1: "service01/{{ host1_fqdn }}"
service2: "service02/{{ host2_fqdn }}"
# End of test fix for https://github.com/freeipa/ansible-freeipa/issues/413
# Test fix for https://github.com/freeipa/ansible-freeipa/issues/411
- name: Add non-existing user to role.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user: nonexisiting_user
action: member
register: result
failed_when: not result.failed
# End of test fix for https://github.com/freeipa/ansible-freeipa/issues/411
# cleanup
- name: Cleanup environment.
ansible.builtin.include_tasks: env_cleanup.yml
ansible-freeipa-master/tests/role/test_role_member_case_insensitive.yml 0000664 0000000 0000000 00000033041 14600563364 0027175 0 ustar 00root root 0000000 0000000 ---
- name: Test role members
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
vars:
user_list:
- User1
- uSer2
- usEr3
group_list:
- Group1
- gRoup2
- grOup3
host_list:
- HoSt01
- hOsT02
hostgroup_list:
- TestHostGroup
service_list:
- MySVC/host01
tasks:
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Test role member case insensitive
block:
# setup
- name: Ensure test role is absent
iparole:
ipaadmin_password: SomeADMINpassword
name: testrule
state: absent
- name: Ensure test users are present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: "{{ item }}"
first: First
last: Last
with_items: "{{ user_list }}"
- name: Ensure test groups are present
ipagroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
with_items: "{{ group_list }}"
- name: Ensure test hosts are present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}.{{ ipaserver_domain }}"
ip_address: 192.168.122.101
force: yes
with_items: "{{ host_list }}"
- name: Ensure test hostgroups are present
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
with_items: "{{ hostgroup_list }}"
- name: Ensure test services are present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}.{{ ipaserver_domain }}"
with_items: "{{ service_list }}"
# Test with action: hbacrule
- name: Check role present with members would trigger a change, mixed case
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
service:
- "{{ service_list[0] }}.{{ ipaserver_domain }}"
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure role is present with members, mixed case
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
service:
- "{{ service_list[0] }}.{{ ipaserver_domain }}"
register: result
failed_when: not result.changed or result.failed
- name: Check role present with members would not trigger a change, mixed case
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
service:
- "{{ service_list[0] }}.{{ ipaserver_domain }}"
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure role is present with members, lowercase
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] | lower }}"
- "{{ user_list[2] | lower }}"
group:
- "{{ group_list[1] | lower }}"
- "{{ group_list[2] | lower }}"
host:
- "{{ host_list[0] | lower }}"
- "{{ host_list[1] | lower }}"
hostgroup:
- "{{ hostgroup_list[0] | lower }}"
service:
- "{{ (service_list[0] + '.' + ipaserver_domain) | lower }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure role is present with members, upercase
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] | upper }}"
- "{{ user_list[2] | upper }}"
group:
- "{{ group_list[1] | upper }}"
- "{{ group_list[2] | upper }}"
host:
- "{{ host_list[0] | upper }}"
- "{{ host_list[1] | upper }}"
hostgroup:
- "{{ hostgroup_list[0] | upper }}"
service:
- "{{ (service_list[0] + '.' + ipaserver_domain) | upper }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure test role is absent
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
state: absent
# Test with action: members
- name: Ensure test role is present
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
- name: Check role members present would trigger a change, mixed case
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
service:
- "{{ service_list[0] }}.{{ ipaserver_domain }}"
action: member
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure role is present with members, mixed case
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
service:
- "{{ service_list[0] }}.{{ ipaserver_domain }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Check role members present would not trigger a change, mixed case
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
service:
- "{{ service_list[0] }}.{{ ipaserver_domain }}"
action: member
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure role is present with members, lowercase
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] | lower }}"
- "{{ user_list[2] | lower }}"
group:
- "{{ group_list[1] | lower }}"
- "{{ group_list[2] | lower }}"
host:
- "{{ host_list[0] | lower }}"
- "{{ host_list[1] | lower }}"
hostgroup:
- "{{ hostgroup_list[0] | lower }}"
service:
- "{{ (service_list[0] + '.' + ipaserver_domain) | lower }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure role is present with members, upercase
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] | upper }}"
- "{{ user_list[2] | upper }}"
group:
- "{{ group_list[1] | upper }}"
- "{{ group_list[2] | upper }}"
host:
- "{{ host_list[0] | upper }}"
- "{{ host_list[1] | upper }}"
hostgroup:
- "{{ hostgroup_list[0] | upper }}"
service:
- "{{ (service_list[0] + '.' + ipaserver_domain) | upper }}"
action: member
register: result
failed_when: result.changed or result.failed
# # Test absent members
- name: Check role members absent would trigger a change, upercase
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] | upper }}"
- "{{ user_list[2] | upper }}"
group:
- "{{ group_list[1] | upper }}"
- "{{ group_list[2] | upper }}"
host:
- "{{ host_list[0] | upper }}"
- "{{ host_list[1] | upper }}"
hostgroup:
- "{{ hostgroup_list[0] | upper }}"
service:
- "{{ (service_list[0] + '.' + ipaserver_domain) | upper }}"
action: member
state: absent
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure role members are absent, upercase
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] | upper }}"
- "{{ user_list[2] | upper }}"
group:
- "{{ group_list[1] | upper }}"
- "{{ group_list[2] | upper }}"
host:
- "{{ host_list[0] | upper }}"
- "{{ host_list[1] | upper }}"
hostgroup:
- "{{ hostgroup_list[0] | upper }}"
service:
- "{{ (service_list[0] + '.' + ipaserver_domain) | upper }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Check role members absent would not trigger a change, upercase
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] | upper }}"
- "{{ user_list[2] | upper }}"
group:
- "{{ group_list[1] | upper }}"
- "{{ group_list[2] | upper }}"
host:
- "{{ host_list[0] | upper }}"
- "{{ host_list[1] | upper }}"
hostgroup:
- "{{ hostgroup_list[0] | upper }}"
service:
- "{{ (service_list[0] + '.' + ipaserver_domain) | upper }}"
action: member
state: absent
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure role members are absent, mixed case
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] }}"
- "{{ user_list[2] }}"
group:
- "{{ group_list[1] }}"
- "{{ group_list[2] }}"
host:
- "{{ host_list[0] }}"
- "{{ host_list[1] }}"
hostgroup:
- "{{ hostgroup_list[0] }}"
service:
- "{{ service_list[0] }}.{{ ipaserver_domain }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure role members are absent, lowercase
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
user:
- "{{ user_list[1] | lower }}"
- "{{ user_list[2] | lower }}"
group:
- "{{ group_list[1] | lower }}"
- "{{ group_list[2] | lower }}"
host:
- "{{ host_list[0] | lower }}"
- "{{ host_list[1] | lower }}"
hostgroup:
- "{{ hostgroup_list[0] | lower }}"
service:
- "{{ (service_list[0] + '.' + ipaserver_domain) | lower }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
always:
- name: Ensure test role is absent
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
state: absent
- name: Ensure test users are absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: "{{ item }}"
state: absent
with_items: "{{ user_list }}"
- name: Ensure test groups are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
with_items: "{{ group_list }}"
- name: Ensure test hosts are absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}.{{ ipaserver_domain }}"
state: absent
with_items: "{{ host_list }}"
- name: Ensure test hostgroups are absent
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
with_items: "{{ hostgroup_list }}"
- name: Ensure test services are absent
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}.{{ ipaserver_domain }}"
continue: yes
state: absent
with_items: "{{ service_list }}"
ansible-freeipa-master/tests/role/test_role_service_member.yml 0000664 0000000 0000000 00000004755 14600563364 0025314 0 ustar 00root root 0000000 0000000 ---
- name: Test service member in role module.
hosts: ipaserver
become: yes
gather_facts: yes
tasks:
- name: Set environment facts.
ansible.builtin.import_tasks: env_facts.yml
- name: Setup environment.
ansible.builtin.import_tasks: env_setup.yml
# tests
- name: Ensure role with member service is present.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
service:
- "service01/{{ host1_fqdn }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure role with member service is present, again.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
service:
- "service01/{{ host1_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure role has member service absent.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
service:
- "service01/{{ host1_fqdn }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has member service absent, again.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
service:
- "service01/{{ host1_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure role has member service with principal name.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
service:
- "service01/{{ host1_fqdn }}@{{ ipaserver_realm }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure role has member service with principal name, again.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
service:
- "service01/{{ host1_fqdn }}@{{ ipaserver_realm }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure role is absent.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure role is absent, again.
iparole:
ipaadmin_password: SomeADMINpassword
name: testrole
state: absent
register: result
failed_when: result.changed or result.failed
# cleanup
- name: Cleanup environment.
ansible.builtin.include_tasks: env_cleanup.yml
ansible-freeipa-master/tests/sanity/ 0000775 0000000 0000000 00000000000 14600563364 0020055 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/sanity/galaxy-importer.cfg 0000664 0000000 0000000 00000000175 14600563364 0023665 0 ustar 00root root 0000000 0000000 [galaxy-importer]
RUN_ANSIBLE_TEST = True
RUN_ANSIBLE_LINT = False
ANSIBLE_TEST_LOCAL_IMAGE = True
LOCAL_IMAGE_DOCKER = True
ansible-freeipa-master/tests/sanity/sanity.sh 0000664 0000000 0000000 00000002060 14600563364 0021716 0 ustar 00root root 0000000 0000000 #!/bin/bash -eu
TOPDIR=$(readlink -f "$(dirname "$0")/../..")
pushd "${TOPDIR}" >/dev/null || exit 1
VENV=/tmp/ansible-test-venv
ANSIBLE_COLLECTION=freeipa-ansible_freeipa
use_docker=$(docker -v >/dev/null 2>&1 && echo "True" || echo "False")
python -m venv "$VENV"
# shellcheck disable=SC1091
source "$VENV"/bin/activate
python -m pip install --upgrade pip
pip install galaxy_importer
rm -f "$ANSIBLE_COLLECTION"-*.tar.gz
rm -f importer_result.json
utils/build-galaxy-release.sh
sed "s/LOCAL_IMAGE_DOCKER = True/LOCAL_IMAGE_DOCKER = ${use_docker}/" < tests/sanity/galaxy-importer.cfg > ${VENV}/galaxy-importer.cfg
export GALAXY_IMPORTER_CONFIG=${VENV}/galaxy-importer.cfg
collection=$(ls -1 "$ANSIBLE_COLLECTION"-*.tar.gz)
echo "Running: python -m galaxy_importer.main $collection"
error=0
while read -r line;
do
if [[ $line == ERROR* ]]; then
((error++))
echo -e "\033[31;1m${line}\033[0m"
else
echo "$line"
fi
done < <(python -m galaxy_importer.main "$collection")
rm -rf "$VENV"
popd >/dev/null || exit 1
exit "$error"
ansible-freeipa-master/tests/selfservice/ 0000775 0000000 0000000 00000000000 14600563364 0021060 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/selfservice/test_selfservice.yml 0000664 0000000 0000000 00000014276 14600563364 0025166 0 ustar 00root root 0000000 0000000 ---
- name: Test selfservice
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
# CLEANUP TEST ITEMS
- name: Ensure selfservice "Users can manage their own name details" is absent
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
state: absent
# CREATE TEST ITEMS
# TESTS
- name: Ensure selfservice "Users can manage their own name details" is present
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
permission: write
attribute:
- givenname
- displayname
- title
register: result
failed_when: not result.changed or result.failed
- name: Ensure selfservice "Users can manage their own name details" is present again
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
permission: write
attribute:
- givenname
- displayname
- title
register: result
failed_when: result.changed or result.failed
- name: Ensure selfservice "Users can manage their own name details" is present with different attribute initials
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
permission: write
attribute:
- initials
register: result
failed_when: not result.changed or result.failed
- name: Ensure selfservice "Users can manage their own name details" is present with different attribute initials again
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
permission: write
attribute:
- initials
register: result
failed_when: result.changed or result.failed
- name: Ensure selfservice "Users can manage their own name details" member attributes givenname, displayname and title are present
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
attribute:
- givenname
- displayname
- title
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure selfservice "Users can manage their own name details" member attributes givenname, displayname and title are present again
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
attribute:
- givenname
- displayname
- title
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure selfservice "Users can manage their own name details" member attribute title is absent
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
attribute:
- title
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure selfservice "Users can manage their own name details" member attribute title is absent again
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
attribute:
- title
action: member
state: absent
register: result
failed_when: result.changed or result.failed
# TEST permission change
- name: Ensure selfservice "Users can manage their own name details" is present with different read,write permission
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
permission: read,write
register: result
failed_when: not result.changed or result.failed
- name: Ensure selfservice "Users can manage their own name details" is present with different read,write permission again
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
permission: read,write
register: result
failed_when: result.changed or result.failed
- name: Ensure selfservice "Users can manage their own name details" fails with bad permission read,read
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
permission: read,read
register: result
failed_when: not result.failed or "Invalid permission" not in result.msg
- name: Ensure selfservice "Users can manage their own name details" fails with bad permission read,write,write
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
permission: read,write,write
register: result
failed_when: not result.failed or "Invalid permission" not in result.msg
- name: Ensure selfservice "Users can manage their own name details" fails with bad attribute title,title
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
attribute:
- title
- title
register: result
failed_when: not result.failed or "Invalid attribute" not in result.msg
# CLEANUP TEST ITEMS
- name: Ensure selfservice "Users can manage their own name details" is absent
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "Users can manage their own name details"
state: absent
ansible-freeipa-master/tests/selfservice/test_selfservice_client_context.yml 0000664 0000000 0000000 00000002451 14600563364 0030260 0 ustar 00root root 0000000 0000000 ---
- name: Test selfservice
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaselfservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test selfservice using client context, in client host.
ansible.builtin.import_playbook: test_selfservice.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test selfservice using client context, in server host.
ansible.builtin.import_playbook: test_selfservice.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/server/ 0000775 0000000 0000000 00000000000 14600563364 0020054 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/server/test_server.yml 0000664 0000000 0000000 00000014101 14600563364 0023141 0 ustar 00root root 0000000 0000000 ---
- name: Test server
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: yes
tasks:
# CLEANUP TEST ITEMS
- name: Ensure ipa_server_name is set
when: ipa_server_name is not defined
block:
- name: Get server name from hostname
ansible.builtin.set_fact:
ipa_server_name: "{{ ansible_facts['fqdn'].split('.')[0] }}"
rescue:
- name: Fallback to 'ipaserver'
ansible.builtin.set_fact:
ipa_server_name: ipaserver
- name: Ensure ipaserver_domain is set
when: ipaserver_domain is not defined
block:
- name: Get domain name from hostname.
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
rescue:
- name: Fallback to 'ipa.test'
ansible.builtin.set_fact:
ipaserver_domain: "ipa.test"
- name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" without location
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ ipa_server_name + '.' + ipaserver_domain }}"
location: ""
- name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" without service weight
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ ipa_server_name + '.' + ipaserver_domain }}"
service_weight: -1
- name: Ensure location "mylocation" is absent
ipalocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: mylocation
state: absent
# CREATE TEST ITEMS
- name: Ensure location "mylocation" is present
ipalocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: mylocation
register: result
failed_when: not result.changed or result.failed
# TESTS
- name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" is present
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ ipa_server_name + '.' + ipaserver_domain }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" with location "mylocation"
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ ipa_server_name + '.' + ipaserver_domain }}"
location: "mylocation"
register: result
failed_when: not result.changed or result.failed
- name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" with location "mylocation" again
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ ipa_server_name + '.' + ipaserver_domain }}"
location: "mylocation"
register: result
failed_when: result.changed or result.failed
- name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" without location
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ ipa_server_name + '.' + ipaserver_domain }}"
location: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" without location again
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ ipa_server_name + '.' + ipaserver_domain }}"
location: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" with service weight 1
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ ipa_server_name + '.' + ipaserver_domain }}"
service_weight: 1
register: result
failed_when: not result.changed or result.failed
- name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" with service weight 1 again
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ ipa_server_name + '.' + ipaserver_domain }}"
service_weight: 1
register: result
failed_when: result.changed or result.failed
- name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" without service weight
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ ipa_server_name + '.' + ipaserver_domain }}"
service_weight: -1
register: result
failed_when: not result.changed or result.failed
- name: Ensure server "{{ ipa_server_name + '.' + ipaserver_domain }}" without service weight again
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ ipa_server_name + '.' + ipaserver_domain }}"
service_weight: -1
register: result
failed_when: result.changed or result.failed
# hidden requires an additional server, not tested
# absent requires an additional server, only sanity test with absent server
- name: Ensure server "{{ 'absent.' + ipaserver_domain }}" is absent
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'absent.' + ipaserver_domain }}"
state: absent
register: result
failed_when: result.changed or result.failed
# ignore_last_of_role requires an additional server, not tested
# ignore_topology_disconnect requires an additional server, not tested
# CLEANUP TEST ITEMS
- name: Ensure location "mylocation" is absent
ipalocation:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: mylocation
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-master/tests/server/test_server_client_context.yml 0000664 0000000 0000000 00000002413 14600563364 0026246 0 ustar 00root root 0000000 0000000 ---
- name: Test server
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaserver:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test server using client context, in client host.
ansible.builtin.import_playbook: test_server.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test server using client context, in server host.
ansible.builtin.import_playbook: test_server.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/service/ 0000775 0000000 0000000 00000000000 14600563364 0020206 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/service/certificate/ 0000775 0000000 0000000 00000000000 14600563364 0022470 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/service/certificate/test_service_certificate.yml 0000664 0000000 0000000 00000014463 14600563364 0030264 0 ustar 00root root 0000000 0000000 ---
- name: Test service certificates
hosts: ipaserver
become: true
tasks:
# setup
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [1, 2]
become: no
delegate_to: localhost
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Get IPv4 address prefix from server node
ansible.builtin.set_fact:
ipv4_prefix: "{{ ansible_facts['default_ipv4'].address.split('.')[:-1] |
join('.') }}"
- name: Set test host FQDN
ansible.builtin.set_fact:
test_subdomain: testcert
test_host: "{{ 'testcert.' + ipaserver_domain }}"
- name: Host test absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ test_host }}"
update_dns: yes
state: absent
- name: Host test present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ test_host }}"
ip_address: "{{ ipv4_prefix + '.201' }}"
update_dns: yes
- name: Ensure testing group group01 is present.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group01
- name: Ensure testing group group02 is present.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group02
- name: Ensure services are absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
continue: yes
state: absent
# tests
- name: Ensure service is present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
certificate:
- "{{ lookup('file', 'cert1.b64') }}"
pac_type:
- MS-PAC
- PAD
auth_ind: otp
force: no
requires_pre_auth: yes
ok_as_delegate: no
ok_to_auth_as_delegate: no
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is present, again
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
certificate:
- "{{ lookup('file', 'cert1.b64') }}"
pac_type:
- MS-PAC
- PAD
auth_ind: otp
force: no
requires_pre_auth: yes
ok_as_delegate: no
ok_to_auth_as_delegate: no
register: result
failed_when: result.changed or result.failed
- name: Ensure service is disabled
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
state: disabled
register: result
failed_when: not result.changed or result.failed
- name: Ensure service member certificate is present.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
certificate:
- "{{ lookup('file', 'cert1.b64') }}"
action: member
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure service member certificate is present, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
certificate:
- "{{ lookup('file', 'cert1.b64') }}"
action: member
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure service multiple member certificates are present, with duplicate.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
certificate:
- "{{ lookup('file', 'cert1.b64') }}"
- "{{ lookup('file', 'cert2.b64') }}"
action: member
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure service member certificate is absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
certificate:
- "{{ lookup('file', 'cert1.b64') }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure service member certificate is absent, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
certificate:
- "{{ lookup('file', 'cert1.b64') }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure service member certificates are absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
certificate:
- "{{ lookup('file', 'cert1.b64') }}"
- "{{ lookup('file', 'cert2.b64') }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure service multiple member certificates is present.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
certificate:
- "{{ lookup('file', 'cert1.b64') }}"
action: member
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is disabled
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
state: disabled
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is disabled, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
state: disabled
register: result
failed_when: result.changed or result.failed
# cleanup
- name: Ensure services are absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ test_host }}"
continue: yes
state: absent
- name: Ensure host is absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ test_host }}"
update_dns: yes
state: absent
- name: Remove certificate files.
ansible.builtin.shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1, 2]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/service/certificate/test_service_certificate_newline.yml 0000664 0000000 0000000 00000014365 14600563364 0032006 0 ustar 00root root 0000000 0000000 ---
- name: Test service with certificates with and without trailing new line
hosts: ipaserver
become: true
tasks:
- name: Include tasks ../../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../../env_freeipa_facts.yml
- name: Setup test environment
ansible.builtin.include_tasks: ../env_vars.yml
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
# The rstrip=False for lookup will add keep the newline at the end of the
# cert and this is automatically revoved in IPA, This is an additional
# test of ipaservice later on to behave correctly in both cases.
- name: Set fact cert1,2,3 from lookup
ansible.builtin.set_fact:
cert1: "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
cert2: "{{ lookup('file', 'cert2.b64', rstrip=True) }}"
cert3: "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
- name: Host {{ svc_fqdn }} absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ svc_fqdn }}"
state: absent
- name: Host {{ svc_fqdn }} present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ svc_fqdn }}"
force: true
register: result
failed_when: not result.changed or result.failed
- name: Service FOO/{{ svc_fqdn }} absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "FOO/{{ svc_fqdn }}"
continue: true
state: absent
- name: Service FOO/{{ svc_fqdn }} present
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "FOO/{{ svc_fqdn }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Service FOO/{{ svc_fqdn }} certs 1,2 members present
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert1 }}"
- "{{ cert2 }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service FOO/{{ svc_fqdn }} certs 1,2 members present again
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert1 }}"
- "{{ cert2 }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Service FOO/{{ svc_fqdn }} certs 1,2,3 members present
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert1 }}"
- "{{ cert2 }}"
- "{{ cert3 }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service FOO/{{ svc_fqdn }} certs 1,2,3 members present again
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert1 }}"
- "{{ cert2 }}"
- "{{ cert3 }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Service FOO/{{ svc_fqdn }} certs 2,3 member absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert2 }}"
- "{{ cert3 }}"
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service FOO/{{ svc_fqdn }} certs 2,3 member absent again
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert2 }}"
- "{{ cert3 }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service FOO/{{ svc_fqdn }} certs 1,2,3 members absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert1 }}"
- "{{ cert2 }}"
- "{{ cert3 }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service FOO/{{ svc_fqdn }} certs 1,2,3 members absent again
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert1 }}"
- "{{ cert2 }}"
- "{{ cert3 }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service FOO/{{ svc_fqdn }} absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "FOO/{{ svc_fqdn }}"
continue: true
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service FOO/{{ svc_fqdn }} absent again
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "FOO/{{ svc_fqdn }}"
continue: true
state: absent
register: result
failed_when: result.changed or result.failed
- name: Host {{ svc_fqdn }} absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ svc_fqdn }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Remove certificate files.
ansible.builtin.shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/service/certificate/test_services_certificate_newline.yml 0000664 0000000 0000000 00000023313 14600563364 0032162 0 ustar 00root root 0000000 0000000 ---
- name: Test services with certificates with and without trailing new line
hosts: ipaserver
become: true
tasks:
- name: Include tasks ../../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../../env_freeipa_facts.yml
- name: Setup test environment
ansible.builtin.include_tasks: ../env_vars.yml
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [11, 12, 13, 21, 22, 23, 31, 32, 33]
become: no
delegate_to: localhost
# The rstrip=False for lookup will add keep the newline at the end of the
# cert and this is automatically revoved in IPA, This is an additional
# test of ipaservice later on to behave correctly in both cases.
- name: Set fact for certs 11,12,13,21,22,23,31,32,33 from lookup
ansible.builtin.set_fact:
cert11: "{{ lookup('file', 'cert11.b64', rstrip=True) }}"
cert12: "{{ lookup('file', 'cert12.b64', rstrip=False) }}"
cert13: "{{ lookup('file', 'cert13.b64', rstrip=True) }}"
cert21: "{{ lookup('file', 'cert21.b64', rstrip=False) }}"
cert22: "{{ lookup('file', 'cert22.b64', rstrip=False) }}"
cert23: "{{ lookup('file', 'cert23.b64', rstrip=True) }}"
cert31: "{{ lookup('file', 'cert31.b64', rstrip=False) }}"
cert32: "{{ lookup('file', 'cert32.b64', rstrip=True) }}"
cert33: "{{ lookup('file', 'cert33.b64', rstrip=False) }}"
- name: Services FOO,BAR,BAZ/{{ svc_fqdn }} absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "FOO/{{ svc_fqdn }}"
- "BAR/{{ svc_fqdn }}"
- "BAZ/{{ svc_fqdn }}"
continue: true
state: absent
- name: Host {{ svc_fqdn }} absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ svc_fqdn }}"
state: absent
- name: Host {{ svc_fqdn }} present
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ svc_fqdn }}"
force: true
register: result
failed_when: not result.changed or result.failed
- name: Services FOO,BAR,BAZ/{{ svc_fqdn }} present
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
services:
- name: "FOO/{{ svc_fqdn }}"
force: yes
- name: "BAR/{{ svc_fqdn }}"
force: yes
- name: "BAZ/{{ svc_fqdn }}"
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Services FOO,BAR,BAZ/{{ svc_fqdn }} present
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
services:
- name: "FOO/{{ svc_fqdn }}"
force: yes
- name: "BAR/{{ svc_fqdn }}"
force: yes
- name: "BAZ/{{ svc_fqdn }}"
force: yes
register: result
failed_when: result.changed or result.failed
- name: Service FOO,BAR,BAZ/{{ svc_fqdn }} certs x1,x2 members present
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
services:
- name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert11 }}"
- "{{ cert12 }}"
- name: "BAR/{{ svc_fqdn }}"
certificate:
- "{{ cert21 }}"
- "{{ cert22 }}"
- name: "BAZ/{{ svc_fqdn }}"
certificate:
- "{{ cert31 }}"
- "{{ cert32 }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service FOO,BAR,BAZ/{{ svc_fqdn }} certs x1,x2 members present again
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
services:
- name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert11 }}"
- "{{ cert12 }}"
- name: "BAR/{{ svc_fqdn }}"
certificate:
- "{{ cert21 }}"
- "{{ cert22 }}"
- name: "BAZ/{{ svc_fqdn }}"
certificate:
- "{{ cert31 }}"
- "{{ cert32 }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Service FOO,BAR,BAZ/{{ svc_fqdn }} certs x1,x2,x3 members present
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
services:
- name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert11 }}"
- "{{ cert12 }}"
- "{{ cert13 }}"
- name: "BAR/{{ svc_fqdn }}"
certificate:
- "{{ cert21 }}"
- "{{ cert22 }}"
- "{{ cert23 }}"
- name: "BAZ/{{ svc_fqdn }}"
certificate:
- "{{ cert31 }}"
- "{{ cert32 }}"
- "{{ cert33 }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service FOO,BAR,BAZ/{{ svc_fqdn }} certs x1,x2,x3 members present again
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
services:
- name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert11 }}"
- "{{ cert12 }}"
- "{{ cert13 }}"
- name: "BAR/{{ svc_fqdn }}"
certificate:
- "{{ cert21 }}"
- "{{ cert22 }}"
- "{{ cert23 }}"
- name: "BAZ/{{ svc_fqdn }}"
certificate:
- "{{ cert31 }}"
- "{{ cert32 }}"
- "{{ cert33 }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Service FOO,BAR,BAZ/{{ svc_fqdn }} certs x2,x3 members absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
services:
- name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert12 }}"
- "{{ cert13 }}"
- name: "BAR/{{ svc_fqdn }}"
certificate:
- "{{ cert22 }}"
- "{{ cert23 }}"
- name: "BAZ/{{ svc_fqdn }}"
certificate:
- "{{ cert32 }}"
- "{{ cert33 }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service FOO,BAR,BAZ/{{ svc_fqdn }} certs x2,x3 members absent, again
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
services:
- name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert12 }}"
- "{{ cert13 }}"
- name: "BAR/{{ svc_fqdn }}"
certificate:
- "{{ cert22 }}"
- "{{ cert23 }}"
- name: "BAZ/{{ svc_fqdn }}"
certificate:
- "{{ cert32 }}"
- "{{ cert33 }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service FOO,BAR,BAZ/{{ svc_fqdn }} certs x1,x2,x3 members absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
services:
- name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert11 }}"
- "{{ cert12 }}"
- "{{ cert13 }}"
- name: "BAR/{{ svc_fqdn }}"
certificate:
- "{{ cert21 }}"
- "{{ cert22 }}"
- "{{ cert23 }}"
- name: "BAZ/{{ svc_fqdn }}"
certificate:
- "{{ cert31 }}"
- "{{ cert32 }}"
- "{{ cert33 }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service FOO,BAR,BAZ/{{ svc_fqdn }} certs x1,x2,x3 members absent, again
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
services:
- name: "FOO/{{ svc_fqdn }}"
certificate:
- "{{ cert11 }}"
- "{{ cert12 }}"
- "{{ cert13 }}"
- name: "BAR/{{ svc_fqdn }}"
certificate:
- "{{ cert21 }}"
- "{{ cert22 }}"
- "{{ cert23 }}"
- name: "BAZ/{{ svc_fqdn }}"
certificate:
- "{{ cert31 }}"
- "{{ cert32 }}"
- "{{ cert33 }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Services FOO,BAR,BAZ/{{ svc_fqdn }} absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "FOO/{{ svc_fqdn }}"
- "BAR/{{ svc_fqdn }}"
- "BAZ/{{ svc_fqdn }}"
continue: true
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Services FOO,BAR,BAZ/{{ svc_fqdn }} absent, again
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "FOO/{{ svc_fqdn }}"
- "BAR/{{ svc_fqdn }}"
- "BAZ/{{ svc_fqdn }}"
continue: true
state: absent
register: result
failed_when: result.changed or result.failed
- name: Host {{ svc_fqdn }} absent
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ svc_fqdn }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Remove certificate files.
ansible.builtin.shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [11, 12, 13, 21, 22, 23, 31, 32, 33]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/service/env_cleanup.yml 0000664 0000000 0000000 00000003770 14600563364 0023237 0 ustar 00root root 0000000 0000000 ---
# Cleanup tasks for the service module tests.
- name: Ensure services are absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "HTTP/{{ svc_fqdn }}"
- "HTTP/{{ nohost_fqdn }}"
- HTTP/svc.ihavenodns.info
- HTTP/no.idontexist.local
- HTTP/no.idontexist.info
- "cifs/{{ host1_fqdn }}"
continue: yes
state: absent
- name: Ensure host "{{ svc_fqdn }}" is absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ svc_fqdn }}"
update_dns: yes
state: absent
- name: Ensure host is absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
- "{{ nohost_fqdn }}"
- svc.ihavenodns.info
update_dns: no
state: absent
- name: Ensure testing users are absent.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- user01
- user02
state: absent
- name: Ensure testing groups are absent.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- group01
- group02
state: absent
- name: Ensure testing hostgroup hostgroup01 is absent.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- hostgroup01
state: absent
- name: Ensure testing hostgroup hostgroup02 is absent.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- hostgroup02
state: absent
- name: Remove IP address for "nohost" host.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ test_domain }}."
name: nohost
del_all: yes
state: absent
ansible-freeipa-master/tests/service/env_setup.yml 0000664 0000000 0000000 00000004101 14600563364 0022735 0 ustar 00root root 0000000 0000000 # Setup environment for service module tests.
---
- name: Setup variables and facts.
ansible.builtin.include_tasks: env_vars.yml
# Cleanup before setup.
- name: Cleanup test environment.
ansible.builtin.include_tasks: env_cleanup.yml
- name: Add IP address for "nohost" host.
ipadnsrecord:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
zone_name: "{{ test_domain }}."
name: nohost
a_ip_address: "{{ ipv4_prefix + '.100' }}"
- name: Add hosts for tests.
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
hosts:
- name: "{{ host1_fqdn }}"
ip_address: "{{ ipv4_prefix + '.101' }}"
- name: "{{ host2_fqdn }}"
ip_address: "{{ ipv4_prefix + '.102' }}"
- name: "{{ svc_fqdn }}"
ip_address: "{{ ipv4_prefix + '.201' }}"
- name: svc.ihavenodns.info
force: yes
update_dns: yes
- name: Ensure testing user user01 is present.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: user01
first: user01
last: last
- name: Ensure testing user user02 is present.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: user02
first: user02
last: last
- name: Ensure testing group group01 is present.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group01
- name: Ensure testing group group02 is present.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group02
- name: Ensure testing hostgroup hostgroup01 is present.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hostgroup01
- name: Ensure testing hostgroup hostgroup02 is present.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: hostgroup02
ansible-freeipa-master/tests/service/env_vars.yml 0000664 0000000 0000000 00000001152 14600563364 0022553 0 ustar 00root root 0000000 0000000 ---
- name: Get Domain from server name
ansible.builtin.set_fact:
test_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
- name: Set host1, host2 and svc hosts fqdn
ansible.builtin.set_fact:
host1_fqdn: "{{ 'host1.' + test_domain }}"
host2_fqdn: "{{ 'host2.' + test_domain }}"
svc_fqdn: "{{ 'svc.' + test_domain }}"
nohost_fqdn: "{{ 'nohost.' + test_domain }}"
- name: Get IPv4 address prefix from server node
ansible.builtin.set_fact:
ipv4_prefix: "{{ ansible_facts['default_ipv4'].address.split('.')[:-1] | join('.') }}"
ansible-freeipa-master/tests/service/generate_test_data.yml 0000664 0000000 0000000 00000004650 14600563364 0024560 0 ustar 00root root 0000000 0000000 # Generate lists for hosts and services
---
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Create present services.json data
ansible.builtin.shell: |
echo "["
for i in $(seq 1 "{{ NUM }}"); do
echo " {"
echo " \"name\": \"HTTP/www$i.{{ DOMAIN }}\","
echo " \"principal\": \"host/test$i.{{ DOMAIN }}\","
echo " \"force\": \"true\""
if [ "$i" -lt "{{ NUM }}" ]; then
echo " },"
else
echo " }"
fi
done
echo "]"
vars:
NUM: 500
DOMAIN: "{{ ipaserver_domain }}"
register: command
- name: Set service_list
ansible.builtin.set_fact:
service_list: "{{ command.stdout | from_json }}"
- name: Create absent services.json data
ansible.builtin.shell: |
echo "["
for i in $(seq 1 "{{ NUM }}"); do
echo " {"
echo " \"name\": \"HTTP/www$i.{{ DOMAIN }}\","
echo " \"continue\": \"true\""
if [ "$i" -lt "{{ NUM }}" ]; then
echo " },"
else
echo " }"
fi
done
echo "]"
vars:
NUM: 500
DOMAIN: "{{ ipaserver_domain }}"
register: command
- name: Set service_absent_list
ansible.builtin.set_fact:
service_absent_list: "{{ command.stdout | from_json }}"
- name: Create present hosts.json data
ansible.builtin.shell: |
echo "["
for i in $(seq 1 "{{ NUM }}"); do
echo " {"
echo " \"name\": \"www$i.{{ DOMAIN }}\","
echo " \"force\": \"true\""
if [ "$i" -lt "{{ NUM }}" ]; then
echo " },"
else
echo " }"
fi
done
echo "]"
vars:
NUM: 500
DOMAIN: "{{ ipaserver_domain }}"
register: command
- name: Set host_list
ansible.builtin.set_fact:
host_list: "{{ command.stdout | from_json }}"
- name: Create absent hosts.json data
ansible.builtin.shell: |
echo "["
for i in $(seq 1 "{{ NUM }}"); do
echo " {"
echo " \"name\": \"www$i.{{ DOMAIN }}\""
if [ "$i" -lt "{{ NUM }}" ]; then
echo " },"
else
echo " }"
fi
done
echo "]"
vars:
NUM: 500
DOMAIN: "{{ ipaserver_domain }}"
register: command
- name: Set host_absent_list
ansible.builtin.set_fact:
host_absent_list: "{{ command.stdout | from_json }}"
ansible-freeipa-master/tests/service/test_service.yml 0000664 0000000 0000000 00000047151 14600563364 0023440 0 ustar 00root root 0000000 0000000 # This test uses skip_host_check, so it will fail if not using
# FreeIPA version 4.7.0 or later.
#
# To test against earlier versions, use test_without_skip_host_check.yml.
#
# This test define 6 hosts:
# - nohost_fqdn: a host with a DNS setup, not enrolled as a host in IPA.
# - no.idontexist.info: a host without DNS and not present in IPA.
# - svc.ihavenodns.inf: a host without DNS, but present in IPA.
# - svc_fqdn: a host with DNS and present in IPA.
# - host1_fqdn and host2_fqdn: used for member actions only.
#
---
- name: Test service
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: yes
tasks:
# setup
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# tests
- name: Tests with skip_host_check, require IPA version 4.8.0+.
when: ipa_version is version('4.7.0', '>=')
block:
- name: Setup test environment
ansible.builtin.include_tasks: env_setup.yml
- name: Ensure service is present
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
pac_type:
- MS-PAC
- PAD
auth_ind: otp
skip_host_check: no
force: yes
requires_pre_auth: yes
ok_as_delegate: no
ok_to_auth_as_delegate: no
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is present, again
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
pac_type:
- MS-PAC
- PAD
auth_ind: otp
skip_host_check: no
force: no
requires_pre_auth: yes
ok_as_delegate: no
ok_to_auth_as_delegate: no
register: result
failed_when: result.changed or result.failed
- name: Modify service.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
pac_type: NONE
ok_as_delegate: yes
ok_to_auth_as_delegate: yes
register: result
failed_when: not result.changed or result.failed
- name: Modify service, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
pac_type: NONE
ok_as_delegate: yes
ok_to_auth_as_delegate: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure service is present, without host object.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ nohost_fqdn }}"
skip_host_check: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is present, without host object, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ nohost_fqdn }}"
skip_host_check: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure service is present, with host not in DNS.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: HTTP/svc.ihavenodns.info
skip_host_check: no
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is present, with host not in DNS, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: HTTP/svc.ihavenodns.info
skip_host_check: no
force: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure service is present, whithout host object and with host not in DNS.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: HTTP/no.idontexist.info
skip_host_check: yes
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is present, whithout host object and with host not in DNS, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: HTTP/no.idontexist.info
skip_host_check: yes
force: yes
register: result
failed_when: result.changed or result.failed
- name: Principal host/test.example.com present in service.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
principal:
- host/test.example.com
action: member
register: result
failed_when: not result.changed or result.failed
- name: Principal host/test.example.com present in service, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
principal:
- host/test.example.com
action: member
register: result
failed_when:
result.changed or (result.failed and "already contains one or more values" not in result.msg)
- name: Principal host/test.example.com absent in service.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
principal:
- host/test.example.com
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Principal host/test.example.com absent in service, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
principal:
- host/test.example.com
action: member
state: absent
register: result
failed_when:
result.changed or (result.failed and "does not contain 'one or more values to remove'" not in result.msg)
- name: Ensure host can manage service.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure host can manage service, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
host: "{{ host1_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure host cannot manage service.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure host cannot manage service, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for users, groups, hosts and hostgroups.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for users, groups, hosts and hostgroups, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for users, groups, hosts and hostgroups.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for users, groups, hosts and hostgroups, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for users, groups, hosts and hostgroups
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for users, groups, hosts and hostgroups, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for users, groups, hosts and hostgroups.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for users, groups, hosts and hostgroups, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure service is absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
continue: yes
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is absent, again
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
continue: yes
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure service is present, with multiple auth_ind values.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
auth_ind: otp,radius
skip_host_check: no
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is present, with multiple auth_ind values, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
auth_ind: otp,radius
skip_host_check: no
force: yes
register: result
failed_when: result.changed or result.failed
- name: Clear auth_ind.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
auth_ind: ""
skip_host_check: no
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Clear auth_ind, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "HTTP/{{ svc_fqdn }}"
auth_ind: ""
skip_host_check: no
force: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure services are absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "HTTP/{{ svc_fqdn }}"
- "HTTP/{{ nohost_fqdn }}"
- HTTP/svc.ihavenodns.info
- HTTP/no.idontexist.local
continue: yes
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure services are absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "HTTP/{{ svc_fqdn }}"
- "HTTP/{{ nohost_fqdn }}"
- HTTP/svc.ihavenodns.info
- HTTP/no.idontexist.local
continue: yes
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure SMB service is present.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
pac_type: NONE
smb: yes
netbiosname: SAMBASVC
register: result
failed_when: not result.changed or result.failed
- name: Ensure SMB service is again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
pac_type: NONE
smb: yes
netbiosname: SAMBASVC
register: result
failed_when: result.changed or result.failed
- name: Modify SMB service.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
smb: yes
netbiosname: SAMBASVC
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
register: result
failed_when: not result.changed or result.failed
- name: Modify SMB service, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ host1_fqdn }}"
smb: yes
netbiosname: SAMBASVC
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
register: result
failed_when: result.changed or result.failed
- name: Ensure SMB service is absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "cifs/{{ host1_fqdn }}"
continue: yes
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure SMB service is absent, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "cifs/{{ host1_fqdn }}"
continue: yes
state: absent
register: result
failed_when: result.changed or result.failed
# cleanup
- name: Cleanup test environment
ansible.builtin.include_tasks: env_cleanup.yml
ansible-freeipa-master/tests/service/test_service_client_context.yml 0000664 0000000 0000000 00000002421 14600563364 0026531 0 ustar 00root root 0000000 0000000 ---
- name: Test service
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test service using client context, in client host.
ansible.builtin.import_playbook: test_service.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test service using client context, in server host.
ansible.builtin.import_playbook: test_service.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/service/test_service_disable.yml 0000664 0000000 0000000 00000007406 14600563364 0025122 0 ustar 00root root 0000000 0000000 # Due to not having some Ansible modules for IPA, some tasks are executed
# in this playbook using the `shell` module, as a Kerberos tikcket is needed
# for these tasks.
# The Kerberos cache is cleaned in the end, so you might need to `kinit` on
# the testing target after running this playbook.
---
- name: Playbook to manage IPA service.
hosts: ipaserver
become: yes
gather_facts: yes
environment:
KRB5CCNAME: test_service_disable_ccache
tasks:
- name: Get Kerberos ticket for `admin`.
ansible.builtin.shell: echo SomeADMINpassword | kinit -c ${KRB5CCNAME} admin
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [1]
become: no
delegate_to: localhost
- name: Ensure service is absent
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc1/{{ ansible_facts['fqdn'] }}"
state: absent
- name: Ensure service is present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc1/{{ ansible_facts['fqdn'] }}"
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
force: no
register: result
failed_when: not result.changed or result.failed
- name: Obtain keytab
ansible.builtin.shell: ipa-getkeytab -s "{{ ansible_facts['fqdn'] }}" -p "mysvc1/{{ ansible_facts['fqdn'] }}" -k mysvc1.keytab
- name: Verify keytab
ansible.builtin.shell: ipa service-find "mysvc1/{{ ansible_facts['fqdn'] }}"
register: result
failed_when: result.failed or result.stdout | regex_search(" Keytab. true")
- name: Ensure service is disabled
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc1/{{ ansible_facts['fqdn'] }}"
state: disabled
register: result
failed_when: not result.changed or result.failed
- name: Verify keytab
ansible.builtin.shell: ipa service-find "mysvc1/{{ ansible_facts['fqdn'] }}"
register: result
failed_when: result.failed or result.stdout | regex_search(" Keytab. true")
- name: Obtain keytab
ansible.builtin.shell: ipa-getkeytab -s "{{ ansible_facts['fqdn'] }}" -p "mysvc1/{{ ansible_facts['fqdn'] }}" -k mysvc1.keytab
- name: Verify keytab
ansible.builtin.shell: ipa service-find "mysvc1/{{ ansible_facts['fqdn'] }}"
register: result
failed_when: result.failed or result.stdout | regex_search(" Keytab. true")
- name: Ensure service is disabled
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc1/{{ ansible_facts['fqdn'] }}"
state: disabled
register: result
failed_when: not result.changed or result.failed
- name: Verify keytab
ansible.builtin.shell: ipa service-find "mysvc1/{{ ansible_facts['fqdn'] }}"
register: result
failed_when: result.failed or result.stdout | regex_search(" Keytab. true")
- name: Ensure service is disabled, with no keytab.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc1/{{ ansible_facts['fqdn'] }}"
state: disabled
register: result
failed_when: result.changed or result.failed
- name: Ensure service is absent
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc1/{{ ansible_facts['fqdn'] }}"
- name: Destroy Kerberos tickets.
ansible.builtin.shell: kdestroy -A -q -c ${KRB5CCNAME}
- name: Remove certificate files.
ansible.builtin.shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/service/test_service_empty_string_params.yml 0000664 0000000 0000000 00000007131 14600563364 0027601 0 ustar 00root root 0000000 0000000 ---
- name: Test service
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: yes
gather_facts: yes
tasks:
# CLEANUP TEST ITEMS
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "test-service/{{ ansible_facts['fqdn'] }}"
continue: yes
state: absent
# CREATE TEST ITEMS
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "test-service/{{ ansible_facts['fqdn'] }}"
register: result
failed_when: not result.changed or result.failed
# TESTS
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with pac_type MS-PAC and PAD
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "test-service/{{ ansible_facts['fqdn'] }}"
pac_type:
- MS-PAC
- PAD
register: result
failed_when: not result.changed or result.failed
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with pac_type MS-PAC and PAD, again
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "test-service/{{ ansible_facts['fqdn'] }}"
pac_type:
- MS-PAC
- PAD
register: result
failed_when: result.changed or result.failed
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with empty pac_type
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "test-service/{{ ansible_facts['fqdn'] }}"
pac_type: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with empty pac_type, again
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "test-service/{{ ansible_facts['fqdn'] }}"
pac_type: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with auth_ind otp and radius
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "test-service/{{ ansible_facts['fqdn'] }}"
auth_ind:
- otp
- radius
register: result
failed_when: not result.changed or result.failed
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with auth_ind otp and radius, again
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "test-service/{{ ansible_facts['fqdn'] }}"
auth_ind:
- otp
- radius
register: result
failed_when: result.changed or result.failed
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with empty auth_ind
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "test-service/{{ ansible_facts['fqdn'] }}"
auth_ind: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with empty auth_ind, again
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "test-service/{{ ansible_facts['fqdn'] }}"
auth_ind: ""
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "test-service/{{ ansible_facts['fqdn'] }}"
continue: yes
state: absent
ansible-freeipa-master/tests/service/test_service_keytab.yml 0000664 0000000 0000000 00000027701 14600563364 0024776 0 ustar 00root root 0000000 0000000 ---
- name: Test service
hosts: ipaserver
become: yes
tasks:
# setup
- name: Setup test envirnoment.
ansible.builtin.include_tasks: env_setup.yml
# Add service to test keytab create/retrieve attributes.
- name: Ensure test service is present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
pac_type:
- MS-PAC
- PAD
auth_ind: otp
force: yes
requires_pre_auth: yes
ok_as_delegate: no
ok_to_auth_as_delegate: no
# tests
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for users.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_user:
- user01
- user02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for users, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_user:
- user01
- user02
action: member
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for users.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_user:
- user01
- user02
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for users, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_user:
- user01
- user02
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for group.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_group:
- group01
- group02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for group, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_group:
- group01
- group02
action: member
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for group.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_group:
- group01
- group02
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for group, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_group:
- group01
- group02
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for host.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for host, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for host.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for host, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for hostgroup.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for hostgroup, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for hostgroup.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for hostgroup, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for users.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_user:
- user01
- user02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for users, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_user:
- user01
- user02
action: member
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for users.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_user:
- user01
- user02
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for users, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_user:
- user01
- user02
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for group.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_group:
- group01
- group02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for group, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_group:
- group01
- group02
action: member
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for group.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_group:
- group01
- group02
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for group, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_group:
- group01
- group02
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for host.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for host, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for host.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for host, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for hostgroup.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for hostgroup, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for hostgroup.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for hostgroup, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
register: result
failed_when: result.changed or result.failed
# cleanup
- name: Clean-up envirnoment.
ansible.builtin.include_tasks: env_cleanup.yml
ansible-freeipa-master/tests/service/test_service_without_skip_host_check.yml 0000664 0000000 0000000 00000032636 14600563364 0030445 0 ustar 00root root 0000000 0000000 ---
- name: Test service without using option skip_host_check
hosts: ipaserver
become: yes
tasks:
# setup
- name: Setup test environment
ansible.builtin.include_tasks: env_setup.yml
# tests
- name: Ensure service is present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
pac_type:
- MS-PAC
- PAD
auth_ind: otp
force: no
requires_pre_auth: yes
ok_as_delegate: no
ok_to_auth_as_delegate: no
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is present, again
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
pac_type:
- MS-PAC
- PAD
auth_ind: otp
force: no
requires_pre_auth: yes
ok_as_delegate: no
ok_to_auth_as_delegate: no
register: result
failed_when: result.changed or result.failed
- name: Modify service.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
pac_type: NONE
ok_as_delegate: yes
ok_to_auth_as_delegate: yes
register: result
failed_when: not result.changed or result.failed
- name: Modify service, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
pac_type: NONE
ok_as_delegate: yes
ok_to_auth_as_delegate: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure service is present, with host not in DNS.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/svc.ihavenodns.info
force: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is present, with host not in DNS, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: HTTP/svc.ihavenodns.info
force: yes
register: result
failed_when: result.changed or result.failed
- name: Principal host/test.example.com present in service.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
principal:
- host/test.example.com
action: member
register: result
failed_when: not result.changed or result.failed
- name: Principal host/test.example.com present in service, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
principal:
- host/test.example.com
action: member
register: result
failed_when:
result.changed or (result.failed and "already contains one or more values" not in result.msg)
- name: Principal host/test.example.com absent in service.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
principal:
- host/test.example.com
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Principal host/test.example.com absent in service, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
principal:
- host/test.example.com
action: member
state: absent
register: result
failed_when:
result.changed or (result.failed and "does not contain 'one or more values to remove'" not in result.msg)
- name: Ensure host can manage service.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure host can manage service, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
host: "{{ host1_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure host cannot manage service.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure host cannot manage service, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for users, groups, hosts and hostgroups.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab present for users, groups, hosts and hostgroups, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for users, groups, hosts and hostgroups.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_create_keytab absent for users, groups, hosts and hostgroups, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for users, groups, hosts and hostgroups
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab present for users, groups, hosts and hostgroups, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
register: result
failed_when: result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for users, groups, hosts and hostgroups.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Service "HTTP/{{ svc_fqdn }}" members allow_retrieve_keytab absent for users, groups, hosts and hostgroups, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent
register: result
failed_when: result.changed or result.failed
#
- name: Ensure service is absent
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
continue: yes
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is absent, again
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
state: absent
register: result
failed_when: result.changed or result.failed
# tests for upstream issue #663
- name: Ensure service is present with principal alias.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc/{{ host1_fqdn }}"
principal: "asvc/{{ host1_fqdn }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure service is present with principal alias, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc/{{ host1_fqdn }}"
principal: "asvc/{{ host1_fqdn }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure service is present with different principal alias.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc/{{ host1_fqdn }}"
principal: "HTTP/{{ host1_fqdn }}"
force: yes
register: result
failed_when: result.failed or not result.changed
- name: Ensure service is presennt with different principal alias, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc/{{ host1_fqdn }}"
principal: "HTTP/{{ host1_fqdn }}"
force: yes
register: result
failed_when: result.failed or result.changed
- name: Ensure service member principal alias is present.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc/{{ host1_fqdn }}"
principal: "asvc/{{ host1_fqdn }}"
action: member
register: result
failed_when: result.failed or not result.changed
- name: Ensure service member principal alias is present, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc/{{ host1_fqdn }}"
principal: "asvc/{{ host1_fqdn }}"
action: member
register: result
failed_when: result.failed or result.changed
- name: Ensure service member principal alias is absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc/{{ host1_fqdn }}"
principal: "asvc/{{ host1_fqdn }}"
action: member
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure service member principal alias is absent, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc/{{ host1_fqdn }}"
principal: "asvc/{{ host1_fqdn }}"
action: member
state: absent
register: result
failed_when: result.failed or result.changed
- name: Ensure service is present with multiple principal aliases.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc/{{ host1_fqdn }}"
principal:
- "HTTP/{{ host1_fqdn }}"
- "asvc/{{ host1_fqdn }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure service is present with multiple principal aliases, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc/{{ host1_fqdn }}"
principal:
- "HTTP/{{ host1_fqdn }}"
- "asvc/{{ host1_fqdn }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure service is with multiple principal aliases is absent.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc/{{ host1_fqdn }}"
continue: yes
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure service is with multiple principal aliases is absent, again.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "mysvc/{{ host1_fqdn }}"
continue: yes
state: absent
register: result
failed_when: result.failed or result.changed
# end of tests for upstream issue #663
# cleanup
- name: Cleanup test environment
ansible.builtin.include_tasks: env_cleanup.yml
ansible-freeipa-master/tests/service/test_services_absent.yml 0000664 0000000 0000000 00000000574 14600563364 0025155 0 ustar 00root root 0000000 0000000 ---
- name: Test services absent
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include generate_test_data.yml
ansible.builtin.include_tasks: generate_test_data.yml
- name: Services absent len:{{ service_list | length }}
ipaservice:
ipaadmin_password: SomeADMINpassword
services: "{{ service_absent_list }}"
state: absent
ansible-freeipa-master/tests/service/test_services_present.yml 0000664 0000000 0000000 00000004122 14600563364 0025352 0 ustar 00root root 0000000 0000000 ---
- name: Test services present
hosts: ipaserver
become: true
gather_facts: true
tasks:
- name: Include generate_test_data.yml
ansible.builtin.include_tasks: generate_test_data.yml
- name: Hosts present len:{{ host_list | length }}
ipahost:
ipaadmin_password: SomeADMINpassword
hosts: "{{ host_list }}"
force: true
register: result
failed_when: not result.changed or result.failed
- name: Hosts present len:{{ host_list | length }}, again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts: "{{ host_list }}"
force: true
register: result
failed_when: result.changed or result.failed
- name: Services present len:{{ service_list | length }}
ipaservice:
ipaadmin_password: SomeADMINpassword
services: "{{ service_list }}"
register: result
failed_when: not result.changed or result.failed
- name: Services present len:{{ service_list | length }}, again
ipaservice:
ipaadmin_password: SomeADMINpassword
services: "{{ service_list }}"
register: result
failed_when: result.changed or result.failed
- name: Services absent len:{{ service_list | length }}
ipaservice:
ipaadmin_password: SomeADMINpassword
services: "{{ service_absent_list }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Services absent len:{{ service_list | length }}, again
ipaservice:
ipaadmin_password: SomeADMINpassword
services: "{{ service_absent_list }}"
state: absent
register: result
failed_when: result.changed or result.failed
- name: Hosts absent len:{{ host_list | length }}
ipahost:
ipaadmin_password: SomeADMINpassword
hosts: "{{ host_absent_list }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Hosts absent len:{{ host_list | length }}, again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts: "{{ host_absent_list }}"
state: absent
register: result
failed_when: result.changed or result.failed
ansible-freeipa-master/tests/service/test_services_present_slice.yml 0000664 0000000 0000000 00000005572 14600563364 0026543 0 ustar 00root root 0000000 0000000 ---
- name: Test services present slice
hosts: ipaserver
become: true
gather_facts: true
vars:
slice_size: 100
tasks:
- name: Include generate_test_data.yml
ansible.builtin.include_tasks: generate_test_data.yml
- name: Size of slice
ansible.builtin.debug:
msg: "{{ slice_size }}"
- name: Size of services list
ansible.builtin.debug:
msg: "{{ service_list | length }}"
- name: Size of hosts list
ansible.builtin.debug:
msg: "{{ host_list | length }}"
- name: Hosts present
ipahost:
ipaadmin_password: SomeADMINpassword
hosts: "{{ host_list[item : item + slice_size] }}"
loop: "{{ range(0, host_list | length, slice_size) | list }}"
register: result
failed_when: not result.changed or result.failed
- name: Hosts present, again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts: "{{ host_list[item : item + slice_size] }}"
loop: "{{ range(0, host_list | length, slice_size) | list }}"
register: result
failed_when: result.changed or result.failed
- name: Services present
ipaservice:
ipaadmin_password: SomeADMINpassword
services: "{{ service_list[item : item + slice_size] }}"
loop: "{{ range(0, service_list | length, slice_size) | list }}"
register: result
failed_when: not result.changed or result.failed
- name: Services present, again
ipaservice:
ipaadmin_password: SomeADMINpassword
services: "{{ service_list[item : item + slice_size] }}"
loop: "{{ range(0, service_list | length, slice_size) | list }}"
register: result
failed_when: result.changed or result.failed
- name: Services absent
ipaservice:
ipaadmin_password: SomeADMINpassword
services: "{{ service_absent_list[item : item + slice_size] }}"
state: absent
loop: "{{ range(0, service_absent_list | length, slice_size) | list }}"
register: result
failed_when: not result.changed or result.failed
- name: Services absent, again
ipaservice:
ipaadmin_password: SomeADMINpassword
services: "{{ service_absent_list[item : item + slice_size] }}"
state: absent
loop: "{{ range(0, service_absent_list | length, slice_size) | list }}"
register: result
failed_when: result.changed or result.failed
- name: Hosts absent
ipahost:
ipaadmin_password: SomeADMINpassword
hosts: "{{ host_absent_list[item : item + slice_size] }}"
state: absent
loop: "{{ range(0, host_absent_list | length, slice_size) | list }}"
register: result
failed_when: not result.changed or result.failed
- name: Hosts absent, again
ipahost:
ipaadmin_password: SomeADMINpassword
hosts: "{{ host_absent_list[item : item + slice_size] }}"
state: absent
loop: "{{ range(0, host_absent_list | length, slice_size) | list }}"
register: result
failed_when: result.changed or result.failed
ansible-freeipa-master/tests/service/test_services_without_skip_host_check.yml 0000664 0000000 0000000 00000006460 14600563364 0030624 0 ustar 00root root 0000000 0000000 ---
- name: Test services without using option skip_host_check
hosts: ipaserver
become: true
tasks:
# setup
- name: Test services without using option skip_host_check
block:
- name: Setup test environment
ansible.builtin.include_tasks: env_setup.yml
- name: Services are present
ipaservice:
ipaadmin_password: SomeADMINpassword
services:
- name: "HTTP/{{ svc_fqdn }}"
principal:
- host/test.example.com
- name: "mysvc/{{ host1_fqdn }}"
pac_type: NONE
ok_as_delegate: yes
ok_to_auth_as_delegate: yes
- name: "HTTP/{{ host1_fqdn }}"
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- "{{ host1_fqdn }}"
- "{{ host2_fqdn }}"
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
- name: "mysvc/{{ host2_fqdn }}"
auth_ind: otp,radius
register: result
failed_when: not result.changed or result.failed
- name: Services are present again
ipaservice:
ipaadmin_password: SomeADMINpassword
services:
- name: "HTTP/{{ svc_fqdn }}"
- name: "mysvc/{{ host1_fqdn }}"
- name: "HTTP/{{ host1_fqdn }}"
- name: "mysvc/{{ host2_fqdn }}"
register: result
failed_when: result.changed or result.failed
# failed_when: not result.failed has been added as this test needs to
# fail because two services with the same name should be added in the same
# task.
- name: Duplicate names in services failure test
ipaservice:
ipaadmin_password: SomeADMINpassword
services:
- name: "HTTP/{{ svc_fqdn }}"
- name: "mysvc/{{ host1_fqdn }}"
- name: "HTTP/{{ nohost_fqdn }}"
- name: "HTTP/{{ svc_fqdn }}"
register: result
failed_when: result.changed or not result.failed or "is used more than once" not in result.msg
- name: Services/name and name 'service' present
ipaservice:
ipaadmin_password: SomeADMINpassword
name: "HTTP/{{ svc_fqdn }}"
services:
- name: "HTTP/{{ svc_fqdn }}"
register: result
failed_when: result.changed or not result.failed or "parameters are mutually exclusive" not in result.msg
- name: Services/name and name are absent
ipaservice:
ipaadmin_password: SomeADMINpassword
register: result
failed_when: result.changed or not result.failed or "one of the following is required" not in result.msg
- name: Name is absent
ipaservice:
ipaadmin_password: SomeADMINpassword
name:
register: result
failed_when: result.changed or not result.failed or "At least one name or services is required" not in result.msg
- name: Only one service can be added at a time using name.
ipaservice:
ipaadmin_password: SomeADMINpassword
name: example.com,example1.com
register: result
failed_when: result.changed or not result.failed or "Only one service can be added at a time using 'name'." not in result.msg
always:
# cleanup
- name: Cleanup test environment
ansible.builtin.include_tasks: env_cleanup.yml
ansible-freeipa-master/tests/servicedelegationrule/ 0000775 0000000 0000000 00000000000 14600563364 0023132 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/servicedelegationrule/test_servicedelegationrule.yml 0000664 0000000 0000000 00000017614 14600563364 0031311 0 ustar 00root root 0000000 0000000 ---
- name: Test servicedelegationrule
hosts: "{{ ipa_test_host | default('ipaserver') }}"
# Change "become" or "gather_facts" to "yes",
# if you test playbook requires any.
become: no
gather_facts: yes
tasks:
# CLEANUP TEST ITEMS
- name: Ensure servicedelegationrule test-delegation-rule is absent
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
state: absent
- name: Ensure service is absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ 'test-service/' + ansible_facts['fqdn'] }}"
- "{{ 'not-existing-test-service/' + ansible_facts['fqdn'] }}"
state: absent
continue: yes
- name: Ensure servicedelegationrule test-delegation-target is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- test-delegation-target
- not-existing-test-delegation-target
state: absent
# CREATE TEST ITEMS
- name: Ensure service test-sevice is present
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'test-service/' + ansible_facts['fqdn'] }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-target is present
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
register: result
failed_when: not result.changed or result.failed
# TESTS
- name: Ensure servicedelegationrule test-delegation-rule is present
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule is present again
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
register: result
failed_when: result.changed or result.failed
- name: Do not fail to ensure absence of not existing servicedelegationrule test-delegation-rule member principal
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
principal: "{{ 'not-existing-test-service/' + ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Do not fail to ensure absence of not existing servicedelegationrule test-delegation-rule member target
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
target: not-existing-test-delegation-target
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member target test-delegation-target is present
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
target: test-delegation-target
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member target test-delegation-target is present, again
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
target: test-delegation-target
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member principal "{{ 'test-service/' + ansible_facts['fqdn'] }}" is present
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
principal: "{{ 'test-service/' + ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member principal "{{ 'test-service/' + ansible_facts['fqdn'] }}" is present again
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
principal: "{{ 'test-service/' + ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member principal "{{ 'test-service/' + ansible_facts['fqdn'] }}" is absent
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
principal: "{{ 'test-service/' + ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member principal "{{ 'test-service/' + ansible_facts['fqdn'] }}" is present absent
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
principal: "{{ 'test-service/' + ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member target test-delegation-target is absent
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
target: test-delegation-target
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member target test-delegation-target is absent, again
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
target: test-delegation-target
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule is absent
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule is absent again
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
state: absent
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure servicedelegationrule test-delegation-target is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
state: absent
- name: Ensure service is absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'test-service/' + ansible_facts['fqdn'] }}"
state: absent
continue: yes
ansible-freeipa-master/tests/servicedelegationrule/test_servicedelegationrule_client_context.yml 0000664 0000000 0000000 00000002634 14600563364 0034407 0 ustar 00root root 0000000 0000000 ---
- name: Test servicedelegationrule
hosts: ipaclients, ipaserver
# Change "become" or "gather_facts" to "yes",
# if you test playbook requires any.
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test servicedelegationrule using client context, in client host.
ansible.builtin.import_playbook: test_servicedelegationrule.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test servicedelegationrule using client context, in server host.
ansible.builtin.import_playbook: test_servicedelegationrule.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
ansible-freeipa-master/tests/servicedelegationrule/test_servicedelegationrule_hostprincipal.yml 0000664 0000000 0000000 00000012533 14600563364 0034243 0 ustar 00root root 0000000 0000000 ---
- name: Test servicedelegationrule_hostprincipal
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: yes
tasks:
# setup
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Host principals are only possible with IPA 4.9.0+
when: ipa_version is version('4.9.0', '>=')
block:
# SET FACTS
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Get REALM from server name
ansible.builtin.set_fact:
ipaserver_realm: "{{ ipaserver_domain | upper }}"
when: ipaserver_realm is not defined
- name: Set test-host fqdn
ansible.builtin.set_fact:
test_host_fqdn: "{{ 'test-host.' + ipaserver_domain }}"
test_host_fqdn_realm: "{{ 'test-host.' + ipaserver_domain + '@' + ipaserver_realm }}"
# CLEANUP TEST ITEMS
- name: Ensure servicedelegationrule test-delegation-rule is absent
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
state: absent
- name: Ensure host is absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ test_host_fqdn }}"
state: absent
# CREATE TEST ITEMS
- name: Ensure host is present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ test_host_fqdn }}"
force: yes
- name: Ensure servicedelegationrule test-delegation-rule is present
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
register: result
failed_when: not result.changed or result.failed
# TESTS
- name: Ensure servicedelegationrule test-delegation-rule member host principal "{{ test_host_fqdn }}" is present
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
principal: "{{ test_host_fqdn }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member host principal "{{ test_host_fqdn }}" is present again
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
principal: "{{ test_host_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member host principal "{{ test_host_fqdn_realm }}" is present unchanged
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
principal: "{{ test_host_fqdn_realm }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member host principal "{{ 'host/' + test_host_fqdn_realm }}" is present unchanged
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
principal: "{{ 'host/' + test_host_fqdn_realm }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member host principal "{{ test_host_fqdn_realm }}" is absent
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
principal: "{{ test_host_fqdn_realm }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationrule test-delegation-rule member host principal "{{ test_host_fqdn }}" is absent unchanged
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
principal: "{{ test_host_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure servicedelegationrule test-delegation-rule is absent
ipaservicedelegationrule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-rule
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure host is absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ test_host_fqdn }}"
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-master/tests/servicedelegationtarget/ 0000775 0000000 0000000 00000000000 14600563364 0023451 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/servicedelegationtarget/test_servicedelegationtarget.yml 0000664 0000000 0000000 00000027653 14600563364 0032153 0 ustar 00root root 0000000 0000000 ---
- name: Test servicedelegationtarget
hosts: "{{ ipa_test_host | default('ipaserver') }}"
# Change "become" or "gather_facts" to "yes",
# if you test playbook requires any.
become: no
gather_facts: yes
tasks:
# CLEANUP TEST ITEMS
- name: Ensure servicedelegationtarget test-delegation-target is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
state: absent
- name: Ensure test services are absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ 'test-service1/' + ansible_facts['fqdn'] }}"
- "{{ 'test-service2/' + ansible_facts['fqdn'] }}"
- "{{ 'test-service3/' + ansible_facts['fqdn'] }}"
- "{{ 'not-existing-test-service/' + ansible_facts['fqdn'] }}"
state: absent
continue: yes
# CREATE TEST ITEMS
- name: Ensure service test-sevice1 is present
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'test-service1/' + ansible_facts['fqdn'] }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure service test-sevice2 is present
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'test-service2/' + ansible_facts['fqdn'] }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure service test-sevice3 is present
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ 'test-service3/' + ansible_facts['fqdn'] }}"
register: result
failed_when: not result.changed or result.failed
# TESTS
- name: Ensure servicedelegationtarget test-delegation-target is present
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target is present again
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
register: result
failed_when: result.changed or result.failed
- name: Do not fail to ensure absence of not existing servicedelegationtarget test-delegation-target member principal
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'not-existing-test-service/' + ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service1/' + ansible_facts['fqdn'] }}" is present
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service1/' + ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service1/' + ansible_facts['fqdn'] }}" is present again
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service1/' + ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service2/' + ansible_facts['fqdn'] }}" is present
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service2/' + ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service2/' + ansible_facts['fqdn'] }}" is present again
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service2/' + ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target principal is empty
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: []
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target principal is empty, again
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: []
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service1/' + ansible_facts['fqdn'] }}" is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service1/' + ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service1/' + ansible_facts['fqdn'] }}" is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service1/' + ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service3/' + ansible_facts['fqdn'] }}" is present
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service3/' + ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service3/' + ansible_facts['fqdn'] }}" is present again
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service3/' + ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target principal
"{{ 'test-service1/' + ansible_facts['fqdn'] }}" and
"{{ 'test-service2/' + ansible_facts['fqdn'] }}" are set
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal:
- "{{ 'test-service1/' + ansible_facts['fqdn'] }}"
- "{{ 'test-service2/' + ansible_facts['fqdn'] }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target principal
"{{ 'test-service1/' + ansible_facts['fqdn'] }}" and
"{{ 'test-service2/' + ansible_facts['fqdn'] }}" are set, again
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal:
- "{{ 'test-service1/' + ansible_facts['fqdn'] }}"
- "{{ 'test-service2/' + ansible_facts['fqdn'] }}"
register: result
failed_when: result.changed or result.failed
- name: Fail if servicedelegationtarget test-delegation-target member principal "{{ 'test-service3/' + ansible_facts['fqdn'] }}" can be removed
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service3/' + ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service1/' + ansible_facts['fqdn'] }}" is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service1/' + ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service1/' + ansible_facts['fqdn'] }}" is absent, again
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service1/' + ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service2/' + ansible_facts['fqdn'] }}" is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service2/' + ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member principal "{{ 'test-service2/' + ansible_facts['fqdn'] }}" is absent, again
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'test-service2/' + ansible_facts['fqdn'] }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target is absent again
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
state: absent
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure test services are absent
ipaservice:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- "{{ 'test-service1/' + ansible_facts['fqdn'] }}"
- "{{ 'test-service2/' + ansible_facts['fqdn'] }}"
- "{{ 'test-service3/' + ansible_facts['fqdn'] }}"
state: absent
continue: yes
ansible-freeipa-master/tests/servicedelegationtarget/test_servicedelegationtarget_client_context.yml0000664 0000000 0000000 00000002650 14600563364 0035243 0 ustar 00root root 0000000 0000000 ---
- name: Test servicedelegationtarget
hosts: ipaclients, ipaserver
# Change "become" or "gather_facts" to "yes",
# if you test playbook requires any.
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test servicedelegationtarget using client context, in client host.
ansible.builtin.import_playbook: test_servicedelegationtarget.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test servicedelegationtarget using client context, in server host.
ansible.builtin.import_playbook: test_servicedelegationtarget.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
ansible-freeipa-master/tests/servicedelegationtarget/test_servicedelegationtarget_hostprincipal.yml 0000664 0000000 0000000 00000012645 14600563364 0035105 0 ustar 00root root 0000000 0000000 ---
- name: Test servicedelegationtarget_hostprincipal
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: yes
tasks:
# setup
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Host principals are only possible with IPA 4.9.0+
when: ipa_version is version('4.9.0', '>=')
block:
# SET FACTS
- name: Get Domain from server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Get REALM from server name
ansible.builtin.set_fact:
ipaserver_realm: "{{ ipaserver_domain | upper }}"
when: ipaserver_realm is not defined
- name: Set test-host fqdn
ansible.builtin.set_fact:
test_host_fqdn: "{{ 'test-host.' + ipaserver_domain }}"
test_host_fqdn_realm: "{{ 'test-host.' + ipaserver_domain + '@' + ipaserver_realm }}"
# CLEANUP TEST ITEMS
- name: Ensure servicedelegationtarget test-delegation-target is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
state: absent
- name: Ensure host is absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ test_host_fqdn }}"
state: absent
# CREATE TEST ITEMS
- name: Ensure host is present
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ test_host_fqdn }}"
force: yes
- name: Ensure servicedelegationtarget test-delegation-target is present
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
register: result
failed_when: not result.changed or result.failed
# TESTS
- name: Ensure servicedelegationtarget test-delegation-target member host principal "{{ test_host_fqdn }}" is present
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ test_host_fqdn }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member host principal "{{ test_host_fqdn }}" is present again
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ test_host_fqdn }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member host principal "{{ test_host_fqdn_realm }}" is present unchanged
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ test_host_fqdn_realm }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member host principal "{{ 'host/' + test_host_fqdn_realm }}" is present unchanged
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ 'host/' + test_host_fqdn_realm }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member host principal "{{ test_host_fqdn_realm }}" is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ test_host_fqdn_realm }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure servicedelegationtarget test-delegation-target member host principal "{{ test_host_fqdn }}" is absent unchanged
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
principal: "{{ test_host_fqdn }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure servicedelegationtarget test-delegation-target is absent
ipaservicedelegationtarget:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test-delegation-target
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure host is absent
ipahost:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: "{{ test_host_fqdn }}"
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-master/tests/sudocmd/ 0000775 0000000 0000000 00000000000 14600563364 0020204 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/sudocmd/test_sudocmd.yml 0000664 0000000 0000000 00000007333 14600563364 0023432 0 ustar 00root root 0000000 0000000 ---
- name: Test sudocmd
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
- name: Ensure sudocmds are absent
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- /usr/bin/su
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: absent
- name: Ensure sudocmd is present
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: /usr/bin/su
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudocmd is present again
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: /usr/bin/su
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure sudocmd is absent
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: /usr/bin/su
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudocmd is absent again
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: /usr/bin/su
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure multiple sudocmd are present
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure multiple sudocmd are present again
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure multiple sudocmd are absent
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure multiple sudocmd are absent again
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudocmds are absent
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- /usr/bin/su
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: absent
- name: Ensure sudocmds are absent
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- /usr/sbin/ifconfig
state: absent
- name: Ensure sudocmds are present
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- /usr/sbin/iwlist
state: present
- name: Ensure multiple sudocmd are absent when only one was present
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-master/tests/sudocmd/test_sudocmd_client_context.yml 0000664 0000000 0000000 00000002421 14600563364 0026525 0 ustar 00root root 0000000 0000000 ---
- name: Test sudocmd
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test sudocmd using client context, in client host.
ansible.builtin.import_playbook: test_sudocmd.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test sudocmd using client context, in server host.
ansible.builtin.import_playbook: test_sudocmd.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/sudocmdgroup/ 0000775 0000000 0000000 00000000000 14600563364 0021261 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/sudocmdgroup/test_sudocmdgroup.yml 0000664 0000000 0000000 00000015704 14600563364 0025565 0 ustar 00root root 0000000 0000000 ---
- name: Test sudocmdgroup
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
- name: Ensure sudocmds are present
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- /usr/bin/su
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: present
- name: Ensure sudocmdgroup is absent
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
state: absent
- name: Ensure sudocmdgroup is present
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudocmdgroup is present again
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure sudocmdgroup is absent
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudocmdgroup is absent again
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudocmdgroup is present, with sudocmds.
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudocmdgroup is present, with sudocmds, again.
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: present
register: result
failed_when: result.changed or result.failed
- name: Verify sudocmdgroup creation with sudocmds
ansible.builtin.shell: |
echo SomeADMINpassword | kinit -c verify_sudocmdgroup admin
KRB5CCNAME="verify_sudocmdgroup" ipa sudocmdgroup-show network --all
kdestroy -A -q -c verify_sudocmdgroup
register: result
failed_when: result.failed or not ("/usr/sbin/ifconfig" in result.stdout and "/usr/sbin/iwlist" in result.stdout)
- name: Ensure sudocmdgroup, with sudocmds, is absent
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudocmdgroup, with sudocmds, is absent again
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure testing sudocmdgroup is present
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudo commands are present in existing sudocmdgroup
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudo commands are present in existing sudocmdgroup, again
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure sudo commands are absent in existing sudocmdgroup
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudo commands are absent in existing sudocmdgroup, again
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudo commands are present in sudocmdgroup
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure one sudo command is not present in sudocmdgroup
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
sudocmd:
- /usr/sbin/ifconfig
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure one sudo command is present in sudocmdgroup
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
sudocmd:
- /usr/sbin/ifconfig
action: member
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure the other sudo command is not present in sudocmdgroup
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
sudocmd:
- /usr/sbin/iwlist
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure the other sudo commandsis not present in sudocmdgroup, again
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: network
sudocmd:
- /usr/sbin/iwlist
action: member
state: absent
register: result
failed_when: result.changed or result.failed
ansible-freeipa-master/tests/sudocmdgroup/test_sudocmdgroup_client_context.yml 0000664 0000000 0000000 00000002457 14600563364 0030670 0 ustar 00root root 0000000 0000000 ---
- name: Test sudocmdgroup
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test sudocmdgroup using client context, in client host.
ansible.builtin.import_playbook: test_sudocmdgroup.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test sudocmdgroup using client context, in server host.
ansible.builtin.import_playbook: test_sudocmdgroup.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/sudorule/ 0000775 0000000 0000000 00000000000 14600563364 0020410 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/sudorule/test_sudorule.yml 0000664 0000000 0000000 00000114625 14600563364 0024045 0 ustar 00root root 0000000 0000000 ---
- name: Test sudorule
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: true
tasks:
# setup
- name: Ensure test user is present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: user01
first: user
last: zeroone
- name: Ensure group01 is present, with user01 on it.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group01
user: user01
- name: Ensure group02 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group02
- name: Ensure sudocmdgroup is absent
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test_sudorule
state: absent
- name: Ensure hostgroup is present, with a host.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: cluster
host: "{{ ansible_facts['fqdn'] }}"
- name: Ensure some sudocmds are available
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- /sbin/ifconfig
- /usr/bin/vim
- /usr/bin/emacs
state: present
- name: Ensure sudocmdgroup is available
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test_sudorule
sudocmd: /usr/bin/vim
state: present
- name: Ensure sudocmdgroup is available
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test_sudorule2
sudocmd: /usr/bin/emacs
state: present
- name: Ensure sudorules are absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- test_upstream_issue_664
- testrule_hostmask
- testrule1
- allusers
- allhosts
- allcommands
state: absent
# tests
- name: Ensure sudorule is present
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present again
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
register: result
failed_when: result.changed or result.failed
- name: Ensure user01 is on the list of users sudorule execute as.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasuser:
- user01
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure user01 is on the list of users sudorule execute as, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasuser:
- user01
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure user01 is not on the list of users sudorule execute as.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasuser:
- user01
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure user01 is not on the list of users sudorule execute as, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasuser:
- user01
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure group01 is on the list of users sudorule execute as.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasuser_group:
- group01
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure group01 is on the list of users sudorule execute as, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasuser_group:
- group01
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure group01 and group2 are on the list of users sudorule execute as.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasuser_group:
- group01
- group02
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure group01 and group2 are on the list of users sudorule execute as, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasuser_group:
- group01
- group02
action: member
register: result
failed_when: result.changed or result.failed
- name: Check if group02 is on the list of users sudorule execute as.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasuser_group:
- group02
action: member
register: result
check_mode: true
failed_when: result.changed or result.failed
- name: Ensure group01 is not on the list of users sudorule execute as.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasuser_group:
- group01
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure group01 is not on the list of users sudorule execute as, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasuser_group:
- group01
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Check if group02 is on the list of users sudorule execute as.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasuser_group:
- group02
action: member
register: result
check_mode: true
failed_when: result.changed or result.failed
- name: Ensure group01 is on the list of group sudorule execute as.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasgroup:
- group01
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure group01 is on the list of group sudorule execute as, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasgroup:
- group01
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure group01 is not on the list of group sudorule execute as.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasgroup:
- group01
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure group01 is not on the list of groups sudorule execute as, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
runasgroup:
- group01
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with usercategory 'all'
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
usercategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with usercategory 'all', again
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
usercategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is with usercategory 'all' is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with runasusercategory 'all'.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
runasusercategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with runasusercategory 'all', again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
runasusercategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is with runasusercategory 'all' is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with runasgroupcategory 'all'.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
runasgroupcategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with runasgroupcategory 'all', again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
runasgroupcategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is with runasgroupcategory 'all' is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with usercategory 'all'.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
usercategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with usercategory 'all', again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
usercategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with hostategory 'all'
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allhosts
hostcategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with hostategory 'all', again
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allhosts
hostcategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is disabled
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
state: disabled
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is disabled, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
state: disabled
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is enabled
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
state: enabled
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is enabled, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
state: enabled
register: result
failed_when: result.changed or result.failed
- name: Ensure user is present in sudorule.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
user: user01
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure user is present in sudorule, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
user: user01
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure user is absent from sudorule.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
user: user01
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure user is absent from sudorule, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
user: user01
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure group is present in sudorule.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
group: group01
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure group is present in sudorule, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
group: group01
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure group is absent from sudorule.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
group: group01
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure group is absent from sudorule, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
group: group01
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule has a sudooption.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
sudooption: '!authenticate'
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule has a sudooption, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
sudooption: '!authenticate'
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule has an order.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
order: 1
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule has an order, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
order: 1
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule has another order.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
order: 10
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present and some sudocmd are allowed.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmd:
- /sbin/ifconfig
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present and some sudocmd are allowed, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmd:
- /sbin/ifconfig
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present and some sudocmd are denyed.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
deny_sudocmd:
- /usr/bin/vim
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present and some sudocmd are denyed, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
deny_sudocmd:
- /usr/bin/vim
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present and, sudocmds are absent.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmd: /sbin/ifconfig
deny_sudocmd: /usr/bin/vim
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present and, sudocmds are absent, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmd: /sbin/ifconfig
deny_sudocmd: /usr/bin/vim
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present with cmdcategory 'all'.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allcommands
cmdcategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present with cmdcategory 'all', again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allcommands
cmdcategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure host "{{ ansible_facts['fqdn'] }}" is present in sudorule.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
host: "{{ ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure host "{{ ansible_facts['fqdn'] }}" is present in sudorule, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
host: "{{ ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure hostgroup is present in sudorule.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
hostgroup: cluster
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure hostgroup is present in sudorule, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
hostgroup: cluster
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with an allow_sudocmdgroup.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmdgroup: test_sudorule
action: member
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with an allow_sudocmdgroup, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmdgroup: test_sudorule
action: member
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, but allow_sudocmdgroup is absent.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmdgroup: test_sudorule
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, but allow_sudocmdgroup is absent.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmdgroup: test_sudorule
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with an deny_sudocmdgroup.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
deny_sudocmdgroup: test_sudorule
action: member
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with an deny_sudocmdgroup, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
deny_sudocmdgroup: test_sudorule
action: member
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, but deny_sudocmdgroup is absent.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
deny_sudocmdgroup: test_sudorule
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, but deny_sudocmdgroup is absent, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
deny_sudocmdgroup: test_sudorule
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with `test_sudorule` sudocmdgroup in allow_sudocmdgroup.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmdgroup: test_sudorule
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with `test_sudorule2` sudocmdgroup in allow_sudocmdgroup.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmdgroup: test_sudorule2
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with both sudocmdgroup in allow_sudocmdgroup.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmdgroup:
- test_sudorule
- test_sudorule2
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with both sudocmdgroup, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmdgroup:
- test_sudorule
- test_sudorule2
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with only `test_sudorule` sudocmdgroup in allow_sudocmdgroup.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
allow_sudocmdgroup: test_sudorule
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with `test_sudorule` sudocmdgroup in deny_sudocmdgroup.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
deny_sudocmdgroup: test_sudorule
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with `test_sudorule2` sudocmdgroup in deny_sudocmdgroup.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
deny_sudocmdgroup: test_sudorule2
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with both sudocmdgroup in deny_sudocmdgroup.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
deny_sudocmdgroup:
- test_sudorule
- test_sudorule2
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with both sudocmdgroup, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
deny_sudocmdgroup:
- test_sudorule
- test_sudorule2
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with only `test_sudorule` sudocmdgroup in deny_sudocmdgroup.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
deny_sudocmdgroup: test_sudorule
state: present
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is absent, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule1
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule allhosts is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allhosts
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule allhosts is absent, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allhosts
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule allusers is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule allusers is absent, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allusers
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule allcommands is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allcommands
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule allcommands is absent, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: allcommands
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule with external user in 'runasuser' is present
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
runasuser:
- apache
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule with external user in 'runasuser' is present, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
runasuser:
- apache
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule member external user in 'runasuser' is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
runasuser:
- apache
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule member external user in 'runasuser' is absent, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
runasuser:
- apache
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule member external user in 'runasuser' is present
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
runasuser:
- apache
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule member external user in 'runasuser' is present, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
runasuser:
- apache
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule with external group in 'runasgroup' is present
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
runasgroup:
- wheel
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule with external group in 'runasgroup' user is present, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
runasgroup:
- wheel
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule member external group in 'runasgroup' is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
runasgroup:
- wheel
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule member external group in 'runasgroup' is absent, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
runasgroup:
- wheel
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule member external group in 'runasgroup' is present
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
runasgroup:
- wheel
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule member external group in 'runasgroup' is present, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
runasgroup:
- wheel
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule 'test_upstream_issue_664' is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: test_upstream_issue_664
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present with hostmask
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule_hostmask
hostmask:
- 192.168.122.1/24
- 192.168.120.1/24
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present with hostmask, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule_hostmask
hostmask:
- 192.168.122.1/24
- 192.168.120.1/24
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule hostmask member is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule_hostmask
hostmask: 192.168.122.0/24
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule hostmask member is absent, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule_hostmask
hostmask: 192.168.122.0/24
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present with another hostmask
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: testrule_hostmask
hostmask: 192.168.122.0/24
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present with another hostmask, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule_hostmask
hostmask: 192.168.122.0/24
register: result
failed_when: result.changed
- name: Check sudorule with hostmask is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule_hostmask
hostmask: 192.168.120.0/24
action: member
register: result
check_mode: yes
failed_when: not result.changed or result.failed
- name: Ensure sudorule hostmask member is present
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule_hostmask
hostmask: 192.168.120.0/24
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule hostmask member is present, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule_hostmask
hostmask: 192.168.120.0/24
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule hostmask member is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule_hostmask
hostmask: 192.168.120.0/24
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule hostmask member is absent, again
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testrule_hostmask
hostmask: 192.168.120.0/24
action: member
state: absent
register: result
failed_when: result.changed or result.failed
# cleanup
- name: Ensure sudocmdgroup is absent
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- test_sudorule
- test_sudorule2
- testrule_hostmask
state: absent
- name: Ensure sudocmds are absent
ipasudocmd:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- /sbin/ifconfig
- /usr/bin/vim
- /usr/bin/emacs
state: absent
- name: Ensure sudorules are absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- test_upstream_issue_664
- testrule1
- allusers
- allhosts
- allcommands
state: absent
- name: Ensure hostgroup is absent.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: cluster
state: absent
- name: Ensure groups are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- group01
- group02
state: absent
- name: Ensure user is absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: user01
state: absent
ansible-freeipa-master/tests/sudorule/test_sudorule_categories.yml 0000664 0000000 0000000 00000017406 14600563364 0026251 0 ustar 00root root 0000000 0000000 ---
- name: Test sudorule user category
hosts: ipaserver
become: yes
gather_facts: yes
tasks:
- name: Get Domain from the server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
- name: Ensure sudorules are absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name:
- allusers
state: absent
- name: Ensure sudorule is present, with usercategory 'all'
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
usercategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with usercategory 'all', again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
usercategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with no usercategory.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
usercategory: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with no usercategory, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
usercategory: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with hostcategory 'all'
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
hostcategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with hostcategory 'all', again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
hostcategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with no usercategory.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
hostcategory: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with no hostcategory, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
hostcategory: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with cmdcategory 'all'
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
cmdcategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with cmdcategory 'all', again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
cmdcategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with no cmdcategory.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
cmdcategory: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with no cmdcategory, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
cmdcategory: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with runasusercategory 'all'
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
runasusercategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with runasusercategory 'all', again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
runasusercategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with no runasusercategory.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
runasusercategory: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with no runasusercategory, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
runasusercategory: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with runasgroupcategory 'all'
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
runasgroupcategory: all
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with runasgroupcategory 'all', again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
runasgroupcategory: all
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorule is present, with no runasgroupcategory.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
runasgroupcategory: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure sudorule is present, with no runasgroupcategory, again.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
runasgroupcategory: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure sudorules are absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name:
- allusers
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure `host` cannot be added if hostcategory is `all`.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
description: sudo rule
host: "{{ 'shouldfail.' + ipaserver_domain }}"
hostcategory: "all"
register: result
failed_when: not result.failed or "Hosts cannot be added when host category='all'" not in result.msg
- name: Ensure `hostgroup` cannot be added if hostcategory is `all`.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
description: sudo rule
hostgroup: shouldfail_hostgroup
hostcategory: "all"
register: result
failed_when: not result.failed or "Hosts cannot be added when host category='all'" not in result.msg
- name: Ensure `user` cannot be added if usercategory is `all`.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
description: sudo rule
user: "shouldfail01"
usercategory: "all"
register: result
failed_when: not result.failed or "Users cannot be added when user category='all'" not in result.msg
- name: Ensure `group` cannot be added if usercategory is `all`.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
description: sudo rule
group: "shouldfail01"
usercategory: "all"
register: result
failed_when: not result.failed or "Users cannot be added when user category='all'" not in result.msg
- name: Ensure `command` cannot be added if cmdcategory is `all`.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
description: sudo rule
allow_sudocmd: "/bin/shouldfail"
cmdcategory: "all"
register: result
failed_when: not result.failed or "Commands cannot be added when command category='all'" not in result.msg
- name: Ensure `command group` cannot be added if cmdcategory is `all`.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
description: sudo rule
allow_sudocmdgroup: shouldfail_cmdgroup
cmdcategory: "all"
register: result
failed_when: not result.failed or "Commands cannot be added when command category='all'" not in result.msg
# cleanup
- name: Ensure sudorules are absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name:
- allusers
state: absent
ansible-freeipa-master/tests/sudorule/test_sudorule_client_context.yml 0000664 0000000 0000000 00000002427 14600563364 0027143 0 ustar 00root root 0000000 0000000 ---
- name: Test sudorule
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipasudorule:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test sudorule using client context, in client host.
ansible.builtin.import_playbook: test_sudorule.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test sudorule using client context, in server host.
ansible.builtin.import_playbook: test_sudorule.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/sudorule/test_sudorule_member_case_insensitive.yml 0000664 0000000 0000000 00000021112 14600563364 0030773 0 ustar 00root root 0000000 0000000 ---
- name: Test sudorule members should be case insensitive.
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
vars:
groups_present:
- eleMENT1
- Element2
- eLeMenT3
- ElemENT4
tasks:
- name: Test sudorule member case insensitive
block:
# SETUP
- name: Ensure domain name
ansible.builtin.set_fact:
ipa_domain: ipa.test
when: ipa_domain is not defined
- name: Ensure test groups exist.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
loop: "{{ groups_present }}"
- name: Ensure test hostgroups exist.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
loop: "{{ groups_present }}"
- name: Ensure test hosts exist.
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}.{{ ipa_domain }}"
force: yes
loop: "{{ groups_present }}"
- name: Ensure test users exist.
ipauser:
ipaadmin_password: SomeADMINpassword
name: "user{{ item }}"
first: "{{ item }}"
last: "{{ item }}"
loop: "{{ groups_present }}"
- name: Ensure sudorule do not exist
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
# TESTS
- name: Start tests.
ansible.builtin.debug:
msg: "Tests are starting."
- name: Ensure sudorule exist with runasusers members
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
cmdcategory: all
runasuser: "user{{ item }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule exist with lowercase runasusers members
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
cmdcategory: all
runasuser: "user{{ item | lower }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule exist with uppercase runasusers members
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
cmdcategory: all
runasuser: "user{{ item | upper }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule exist with runasgroup members
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
cmdcategory: all
runasgroup: "{{ item }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule exist with lowercase runasgroup members
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
cmdcategory: all
runasgroup: "{{ item | lower }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule exist with uppercase runasgroup members
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
cmdcategory: all
runasgroup: "{{ item | upper }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule do not exist
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
#####
- name: Ensure sudorule exist with members
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
cmdcategory: all
hostgroup: "{{ item }}"
host: "{{ item }}.{{ ipa_domain }}"
group: "{{ item }}"
user: "user{{ item }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule exist with members, lowercase
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
cmdcategory: all
hostgroup: "{{ item | lower }}"
host: "{{ item | lower }}.{{ ipa_domain }}"
group: "{{ item | lower }}"
user: "user{{ item | lower }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule exist with members, uppercase
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
cmdcategory: all
hostgroup: "{{ item | upper }}"
host: "{{ item | upper }}.{{ ipa_domain }}"
group: "{{ item | upper }}"
user: "user{{ item | upper }}"
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule member is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "{{ item }}"
host: "{{ item }}.{{ ipa_domain }}"
group: "{{ item }}"
user: "user{{ item }}"
action: member
state: absent
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule member is absent, lowercase
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "{{ item | lower }}"
host: "{{ item | lower }}.{{ ipa_domain }}"
group: "{{ item | lower }}"
user: "user{{ item | lower }}"
action: member
state: absent
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule member is absent, upercase
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "{{ item | upper }}"
host: "{{ item | upper }}.{{ ipa_domain }}"
group: "{{ item | upper }}"
user: "user{{ item | upper }}"
action: member
state: absent
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule member is present, upercase
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "{{ item | upper }}"
host: "{{ item | upper }}.{{ ipa_domain }}"
group: "{{ item | upper }}"
user: "user{{ item | upper }}"
action: member
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule member is present, lowercase
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "{{ item | lower }}"
host: "{{ item | lower }}.{{ ipa_domain }}"
group: "{{ item | lower }}"
user: "user{{ item | lower }}"
action: member
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule member is present, mixed case
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
hostgroup: "{{ item }}"
host: "{{ item }}.{{ ipa_domain }}"
group: "{{ item }}"
user: "user{{ item }}"
action: member
loop: "{{ groups_present }}"
register: result
failed_when: result.failed or result.changed
- name: End tests.
ansible.builtin.debug:
msg: "All tests executed."
always:
# cleanup
- name: Ensure sudorule do not exist
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test groups do not exist.
ipagroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test hostgroups do not exist.
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test hosts do not exist.
ipahost:
ipaadmin_password: SomeADMINpassword
name: "{{ item }}.{{ ipa_domain }}"
state: absent
loop: "{{ groups_present }}"
- name: Ensure test users do not exist.
ipauser:
ipaadmin_password: SomeADMINpassword
name: "user{{ item }}"
state: absent
loop: "{{ groups_present }}"
ansible-freeipa-master/tests/sudorule/test_sudorule_single_hostnames.yml 0000664 0000000 0000000 00000011046 14600563364 0027460 0 ustar 00root root 0000000 0000000 ---
- name: Test sudorule with single hostnames.
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
tasks:
- name: Test sudorule single hostnames
block:
# setup test environment
- name: Get Domain from the server name
ansible.builtin.set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
when: ipaserver_domain is not defined
- name: Ensure test sudo rule is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
state: absent
- name: Ensure test host exist
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "host01.{{ ipaserver_domain }}"
force: yes
- name: "host02.{{ ipaserver_domain }}"
force: yes
# start tests
- name: Ensure sudorule exist with host member using FQDN.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
host: "host01.{{ ipaserver_domain }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule host member using short hostname.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
host: host01
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule exist with another host using short name.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
host: host02
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule exist with another host member using FQDN.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
host: "host02.{{ ipaserver_domain }}"
register: result
failed_when: result.failed or result.changed
- name: Ensure sudorule exist with another host member using FQDN.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
host: "host02.{{ ipaserver_domain }}"
register: result
failed_when: result.failed or result.changed
# cleanup for member tests.
- name: Ensure test sudo rule is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
state: absent
- name: Ensure test sudo rule is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
state: absent
# member tests
- name: Ensure test sudo rule is present
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
- name: Ensure sudorule host member using FQDN.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
host: "host01.{{ ipaserver_domain }}"
action: member
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule host member using short hostname.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
host: host01
action: member
register: result
failed_when: result.failed or result.changed
- name: Ensure test sudo rule is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
state: absent
- name: Ensure test sudo rule is present
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
- name: Ensure sudorule host member using FQDN.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
host: "host01.{{ ipaserver_domain }}"
action: member
register: result
failed_when: result.failed or not result.changed
- name: Ensure sudorule host member using short hostname.
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
host: host01
action: member
register: result
failed_when: result.failed or result.changed
always:
# cleanup
- name: Ensure test sudo rule is absent
ipasudorule:
ipaadmin_password: SomeADMINpassword
name: sudorule_for_hosts
state: absent
- name: Ensure test host is absent
ipahost:
ipaadmin_password: SomeADMINpassword
name:
- "host01.{{ ipaserver_domain }}"
- "host02.{{ ipaserver_domain }}"
state: absent
ansible-freeipa-master/tests/test_playbook_runs.py 0000664 0000000 0000000 00000004632 14600563364 0023053 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# Authors:
# Sergio Oliveira Campos
#
# Copyright (C) 2020 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
import pytest
import functools
from unittest import TestCase
from utils import (
get_test_playbooks, get_server_host, run_playbook, get_enabled_test,
get_disabled_test
)
def prepare_test(testname, testpath):
"""
Decorate tests generated automatically from playbooks.
Injects 2 arguments to the test (`test_path` and `test_name`) and
name the test method using test name (to ensure test reports are useful).
"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
kwargs["test_path"] = testpath
kwargs["test_name"] = testname
return func(*args, **kwargs)
return wrapper
decorator.__name__ = testname
return decorator
if not get_server_host():
raise RuntimeError("IPA_SERVER_HOST is not set.")
# Dynamically create the TestCase classes with respective
# test_* methods.
for test_dir_name, playbooks_in_dir in get_test_playbooks().items():
_tests = {}
for playbook in playbooks_in_dir:
test_name = playbook["name"].replace("-", "_")
test_path = playbook["path"]
if (
get_enabled_test(test_dir_name, test_name)
and not get_disabled_test(test_dir_name, test_name)
):
# pylint: disable=W0621,W0640,W0613
@pytest.mark.playbook
@prepare_test(test_name, test_path)
def method(self, test_path, test_name):
run_playbook(test_path)
# pylint: enable=W0621,W0640,W0613
_tests[test_name] = method
globals()[test_dir_name] = type(test_dir_name, tuple([TestCase]), _tests,)
ansible-freeipa-master/tests/trust/ 0000775 0000000 0000000 00000000000 14600563364 0017727 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/trust/test_trust.yml 0000664 0000000 0000000 00000013770 14600563364 0022702 0 ustar 00root root 0000000 0000000 ---
- name: Test ipatrust
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
vars:
adserver:
domain: "{{ winserver_domain | default('windows.local')}}"
realm: "{{ winserver_realm | default(winserver_domain) | default('windows.local') | upper }}"
password: "{{ winserver_admin_password | default('SomeW1Npassword') }}"
ipaserver:
domain: "{{ ipaserver_domain | default('ipa.test')}}"
realm: "{{ ipaserver_realm | default(ipaserver_domain) | default('ipa.test') | upper }}"
trust_exists: 'Realm name: {{ adserver.domain }}'
ad_range_exists: 'Range name: {{ adserver.realm }}_id_range'
ipa_range_exists: 'Range name: {{ ipaserver.realm }}_subid_range'
tasks:
- name: Run tust tests, if supported by environment
when: trust_test_is_supported | default(false)
block:
- name: Delete test trust
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
realm: "{{ adserver.domain }}"
state: absent
- name: Clear test idranges
ansible.builtin.shell: |
kinit -c test_krb5_cache admin <<< SomeADMINpassword
ipa idrange-del {{ adserver.realm }}_id_range || true
ipa idrange-del {{ ipaserver.realm }}_subid_range || true
kdestroy -c test_krb5_cache -q -A
- name: Add trust with range_type 'ipa-ad-trust'
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
realm: "{{ adserver.domain }}"
admin: Administrator
trust_type: ad
range_type: ipa-ad-trust
password: "{{ adserver.password }}"
state: present
register: result
failed_when: result.failed or not result.changed
- name: Check if 'ipa-ad-trust' trust exists
ansible.builtin.shell: |
echo 'SomeADMINpassword' | kinit admin
ipa trust-find
kdestroy -c test_krb5_cache -q -A
register: check_add_trust
failed_when: "trust_exists not in check_add_trust.stdout"
- name: Add trust with range_type 'ipa-ad-trust', again
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
realm: "{{ adserver.domain }}"
admin: Administrator
range_type: ipa-ad-trust
password: "{{ adserver.password }}"
state: present
register: result
failed_when: result.failed or result.changed
- name: Delete 'ipa-ad-trust' trust
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
realm: "{{ adserver.domain }}"
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Check if 'ipa-ad-trust' trust was removed
ansible.builtin.shell: |
kinit -c test_krb5_cache admin <<< SomeADMINpassword
ipa trust-find
kdestroy -c test_krb5_cache -q -A
register: check_add_trust
failed_when: "trust_exists in check_add_trust.stdout"
- name: Delete 'ipa-ad-trust' trust, again
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
realm: "{{ adserver.domain }}"
state: absent
register: result
failed_when: result.failed or result.changed
- name: Clear test idranges
ansible.builtin.shell: |
kinit -c test_krb5_cache admin <<< SomeADMINpassword
ipa idrange-del {{ adserver.realm }}_id_range || true
ipa idrange-del {{ ipaserver.realm }}_subid_range || true
kdestroy -c test_krb5_cache -q -A
- name: Add trust with range_type 'ipa-ad-trust-posix'
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
realm: "{{ adserver.domain }}"
admin: Administrator
range_type: ipa-ad-trust-posix
password: "{{ adserver.password }}"
state: present
register: result
failed_when: result.failed or not result.changed
- name: Check if 'ipa-ad-trust-posix' trust exists
ansible.builtin.shell: |
kinit -c test_krb5_cache admin <<< SomeADMINpassword
ipa trust-find
kdestroy -c test_krb5_cache -q -A
register: check_add_trust
failed_when: "trust_exists not in check_add_trust.stdout"
- name: Add trust with range_type 'ipa-ad-trust-posix', again
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
realm: "{{ adserver.domain }}"
admin: Administrator
range_type: ipa-ad-trust-posix
password: "{{ adserver.password }}"
state: present
register: result
failed_when: result.failed or result.changed
- name: Delete 'ipa-ad-trust-posix' trust
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
realm: "{{ adserver.domain }}"
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Check if trust 'ipa-ad-trust-posix' was removed
ansible.builtin.shell: |
kinit -c test_krb5_cache admin <<< SomeADMINpassword
ipa trust-find
kdestroy -c test_krb5_cache -q -A
register: check_del_trust
failed_when: "trust_exists in check_del_trust.stdout"
- name: Delete 'ipa-ad-trust-posix' trust, again
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
realm: "{{ adserver.domain }}"
state: absent
register: result
failed_when: result.failed or result.changed
- name: Clear test idranges
ansible.builtin.shell: |
kinit -c test_krb5_cache admin <<< SomeADMINpassword
ipa idrange-del {{ adserver.realm }}_id_range || true
ipa idrange-del {{ ipaserver.realm }}_subid_range || true
kdestroy -c test_krb5_cache -q -A
ansible-freeipa-master/tests/trust/test_trust_client_context.yml 0000664 0000000 0000000 00000002412 14600563364 0025773 0 ustar 00root root 0000000 0000000 ---
- name: Test trust
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
realm: this.test.should.fail
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test trust using client context, in client host.
ansible.builtin.import_playbook: test_trust.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test trust using client context, in server host.
ansible.builtin.import_playbook: test_trust.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/user/ 0000775 0000000 0000000 00000000000 14600563364 0017524 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/user/certificate/ 0000775 0000000 0000000 00000000000 14600563364 0022006 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/user/certificate/test_user_certificate.yml 0000664 0000000 0000000 00000005312 14600563364 0027111 0 ustar 00root root 0000000 0000000 ---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
- name: User test present
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
first: test
last: test
- name: User test cert members present
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: User test cert members present again
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: User test cert members absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: User test cert members absent again
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: User test absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Remove certificate files.
ansible.builtin.shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/user/certificate/test_users_certificate.yml 0000664 0000000 0000000 00000005720 14600563364 0027277 0 ustar 00root root 0000000 0000000 ---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
- name: User test absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
state: absent
- name: User test present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
first: test
last: test
- name: User test cert members present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: User test cert members present again
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: User test cert members absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: User test cert members absent again
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: User test absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Remove certificate files.
ansible.builtin.shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/user/certmapdata/ 0000775 0000000 0000000 00000000000 14600563364 0022011 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/user/certmapdata/test_user_certmapdata.yml 0000664 0000000 0000000 00000015464 14600563364 0027130 0 ustar 00root root 0000000 0000000 ---
- name: Test user certmapdata
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
- name: User test absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
state: absent
- name: User test present
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
first: test
last: test
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members present
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- certificate: "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members present again
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- certificate: "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: User test certmapdata members absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- certificate: "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members absent again
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- certificate: "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User test certmapdata members present
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=issuer1
subject: CN=subject1
- issuer: CN=issuer2
subject: CN=subject2
- issuer: CN=issuer3
subject: CN=subject3
action: member
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members present again
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=issuer1
subject: CN=subject1
- issuer: CN=issuer2
subject: CN=subject2
- issuer: CN=issuer3
subject: CN=subject3
action: member
register: result
failed_when: result.changed or result.failed
- name: User test certmapdata members absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=issuer1
subject: CN=subject1
- issuer: CN=issuer3
subject: CN=subject3
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members absent again
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=issuer1
subject: CN=subject1
- issuer: CN=issuer3
subject: CN=subject3
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User test certmapdata members absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=issuer2
subject: CN=subject2
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members absent again
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=issuer2
subject: CN=subject2
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User test certmapdata member present
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=ca,dc=example,dc=com
subject: CN=test,dc=example,dc=com
action: member
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata member present again
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=ca,dc=example,dc=com
subject: CN=test,dc=example,dc=com
action: member
register: result
failed_when: result.changed or result.failed
- name: User test certmapdata member (data) present again
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- data: X509:dc=com,dc=example,CN=cadc=com,dc=example,CN=test
action: member
register: result
failed_when: result.changed or result.failed
- name: User test certmapdata member absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=ca,dc=example,dc=com
subject: CN=test,dc=example,dc=com
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata member (data) absent again
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- data: X509:dc=com,dc=example,CN=cadc=com,dc=example,CN=test
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User test absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Remove certificate files.
ansible.builtin.shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/user/certmapdata/test_user_certmapdata_issuer_subject.yml 0000664 0000000 0000000 00000004354 14600563364 0032235 0 ustar 00root root 0000000 0000000 ---
- name: Test user certmapdata
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: User test absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
state: absent
- name: User test present
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
first: test
last: test
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members present
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=issuer1
subject: CN=subject1
- issuer: CN=issuer2
subject: CN=subject2
- issuer: CN=issuer3
subject: CN=subject3
action: member
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members present again
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=issuer1
subject: CN=subject1
- issuer: CN=issuer2
subject: CN=subject2
- issuer: CN=issuer3
subject: CN=subject3
action: member
register: result
failed_when: result.changed or result.failed
- name: User test certmapdata members absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=issuer1
subject: CN=subject1
- issuer: CN=issuer2
subject: CN=subject2
- issuer: CN=issuer3
subject: CN=subject3
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members absent again
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certmapdata:
- issuer: CN=issuer1
subject: CN=subject1
- issuer: CN=issuer2
subject: CN=subject2
- issuer: CN=issuer3
subject: CN=subject3
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User test absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-master/tests/user/certmapdata/test_users_certmapdata.yml 0000664 0000000 0000000 00000011677 14600563364 0027315 0 ustar 00root root 0000000 0000000 ---
- name: Test user certmapdata
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
- name: User test absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
state: absent
- name: User test present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
first: test
last: test
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certmapdata:
- certificate: "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members present again
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certmapdata:
- certificate: "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: User test certmapdata members absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certmapdata:
- certificate: "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members absent again
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certmapdata:
- certificate: "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
- certificate: "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User test certmapdata members present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certmapdata:
- issuer: CN=issuer1
subject: CN=subject1
- issuer: CN=issuer2
subject: CN=subject2
- issuer: CN=issuer3
subject: CN=subject3
action: member
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members present again
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certmapdata:
- issuer: CN=issuer1
subject: CN=subject1
- issuer: CN=issuer2
subject: CN=subject2
- issuer: CN=issuer3
subject: CN=subject3
action: member
register: result
failed_when: result.changed or result.failed
- name: User test certmapdata members absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certmapdata:
- issuer: CN=issuer1
subject: CN=subject1
- issuer: CN=issuer2
subject: CN=subject2
- issuer: CN=issuer3
subject: CN=subject3
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User test certmapdata members absent again
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certmapdata:
- issuer: CN=issuer1
subject: CN=subject1
- issuer: CN=issuer2
subject: CN=subject2
- issuer: CN=issuer3
subject: CN=subject3
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User test absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Remove certificate files.
ansible.builtin.shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1, 2, 3]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/user/create_users_json.yml 0000664 0000000 0000000 00000000462 14600563364 0023766 0 ustar 00root root 0000000 0000000 ---
- name: Create users.json
hosts: localhost
tasks:
- name: Check if users.json exists
ansible.builtin.stat:
path: users.json
register: register_stat_users
- name: Create users.json
ansible.builtin.command: /bin/bash users.sh 500
when: not register_stat_users.stat.exists
ansible-freeipa-master/tests/user/test_user.yml 0000664 0000000 0000000 00000040671 14600563364 0022274 0 ustar 00root root 0000000 0000000 ---
- name: Test user
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: manager1,manager2,manager3,pinky,pinky2,igagarin,reddy
state: absent
- name: User manager1 present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: manager1
first: Manager
last: One
register: result
failed_when: not result.changed or result.failed
- name: User manager2 present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: manager2
first: Manager
last: One
register: result
failed_when: not result.changed or result.failed
- name: User manager3 present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: manager3
first: Manager
last: One
register: result
failed_when: not result.changed or result.failed
- name: User pinky present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
uid: 10001
gid: 100
phone: "+555123457"
email: pinky@acme.com
principalexpiration: "21220119235959"
passwordexpiration: "2122-01-19 23:59:59"
first: pinky
last: Acme
initials: pa
#password: foo2
principal: pa
random: yes
street: PinkyStreet
city: PinkyCity
userstate: PinkyState
postalcode: PinkyZip
mobile: "+555123458,+555123459"
pager: "+555123450,+555123451"
fax: "+555123452,+555123453"
orgunit: PinkyOrgUnit
manager: manager1,manager2
update_password: on_create
carlicense: PinkyCarLicense1,PinkyCarLicense2
# sshpubkey
userauthtype: password,radius,otp
userclass: PinkyUserClass
#radius: "http://some.link/"
#radiususer: PinkyRadiusUser
departmentnumber: "1234"
employeenumber: "0815"
employeetype: "PinkyExmployeeType"
preferredlanguage: "en"
# certificate
noprivate: yes
nomembers: false
#issuer: PinkyIssuer
#subject: PinkySubject
register: result
failed_when: not result.changed or result.failed
- name: Ensure user presence with 'random:false'
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
first: pinky
last: Acme
random: false
register: result
failed_when: result.changed or result.failed
- name: Set street, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
street: PinkyStreet
register: result
failed_when: result.changed or result.failed
- name: Clear street attribute.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
street: ""
register: result
failed_when: not result.changed or result.failed
- name: Clear street attribute, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
street: ""
register: result
failed_when: result.changed or result.failed
- name: User pinky present with changed settings
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
first: pinky
last: Acme
manager: []
principal: []
sshpubkey:
# yamllint disable-line rule:line-length
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqmVDpEX5gnSjKuv97AyzOhaUMMKz8ahOA3GY77tVC4o68KNgMCmDSEG1/kOIaElngNLaCha3p/2iAcU9Bi1tLKUlm2bbO5NHNwHfRxY/3cJtq+/7D1vxJzqThYwI4F9vr1WxyY2+mMTv3pXbfAJoR8Mu06XaEY5PDetlDKjHLuNWF+/O7ZU8PsULTa1dJZFrtXeFpmUoLoGxQBvlrlcPI1zDciCSU24t27Zan5Py2l5QchyI7yhCyMM77KDtj5+AFVpmkb9+zq50rYJAyFVeyUvwjzErvQrKJzYpA0NyBp7vskWbt36M16/M/LxEK7HA6mkcakO3ESWx5MT1LAjvdlnxbWG3787MxweHXuB8CZU+9bZPFBaJ+VQtOfJ7I8eH0S16moPC4ak8FlcFvOH8ERDPWLFDqfy09yaZ7bVIF0//5ZI7Nf3YDe3S7GrBX5ieYuECyP6UNkTx9BRsAQeVvXEc6otzB7iCSnYBMGUGzCqeigoAWaVQUONsSR3Uatks= pinky@ipaserver.el81.local # noqa 204
# yamllint disable-line rule:line-length
- AAAAB3NzaC1yc2EAAAADAQABAAABgQDc8MIjaSrxLYHvu+hduoF4m6NUFSlXZWzYbd3BK4L47/U4eiXoOS6dcfuZJDjmLfOipc7XVp7NADwAgA1yBOAjbeVpXr2tC8w8saZibl75WBOEjDfNroiOh/f/ojrwwHg05QTVSZHs27sU1HBPyCQM/FHVM6EnRfmyiBkEBA/3ca0PJ9UJhWb2XisCaz6y6QcTh4gQnvHzgmEmK31GwiKnmBSEQuj8P5NGCO8RlN3cq3zpRpMDEoBRCjQYicllf/5P43r5OGvS1LhTiAMfyqE37URezNQa7aozBpH1GhIwAmjAtm84jXQjxUgZPYC0aSLuADYErScOP4792r6koH9t/DM5/M+jG2c4PNWynDczUw6Eaxl5E3hU0Ee9UN0Oee7iBnVenS/QMeZNyo5lMA/HXT5lrYiJGTYM0shRjGXXYBbJZhWerguSWDAdUd1gvuGP1nb7/+/Cvb46+HX7zYouS5Ojo0yPzMZ07X142jnKAfx9LnKdMUCwBJzbtoJ91Zc= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: not result.changed or result.failed
- name: User pinky add manager manager1
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
manager: manager1
action: member
register: result
failed_when: not result.changed or result.failed
- name: User pinky add manager manager1 again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
manager: manager1
action: member
register: result
failed_when: result.changed or result.failed
- name: User pinky add manager manager2, manager3
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
manager: manager2,manager3
action: member
register: result
failed_when: not result.changed or result.failed
- name: User pinky add manager manager2, manager3 again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
manager: manager2,manager3
action: member
register: result
failed_when: result.changed or result.failed
- name: User pinky remove manager manager1
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
manager: manager1
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User pinky remove manager manager1 again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
manager: manager1
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User pinky add principal pa
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
principal: pa
action: member
register: result
failed_when: not result.changed or result.failed
- name: User pinky add principal pa again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
principal: pa
action: member
register: result
failed_when: result.changed or result.failed
- name: User pinky add principal pa1
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
principal: pa1
action: member
register: result
failed_when: not result.changed or result.failed
- name: User pinky remove principal pa1
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
principal: pa1
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User pinky remove principal pa1 again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
principal: pa1
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User pinky remove principal pa
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
principal: pa
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User pinky remove principal non-existing pa2
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
principal: pa2
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User pinky absent and preserved
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
preserve: yes
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User pinky absent and preserved, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
preserve: yes
state: absent
register: result
failed_when: result.changed or result.failed
- name: User pinky undeleted (preserved before)
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
state: undeleted
register: result
failed_when: not result.changed or result.failed
- name: User pinky undeleted (preserved before), again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
state: undeleted
register: result
failed_when: result.changed or result.failed
- name: Users pinky disabled
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
state: disabled
register: result
failed_when: not result.changed or result.failed
- name: Users pinky disabled, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
state: disabled
register: result
failed_when: result.changed or result.failed
- name: User pinky enabled
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
state: enabled
register: result
failed_when: not result.changed or result.failed
- name: User pinky enabled, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
state: enabled
register: result
failed_when: result.changed or result.failed
- name: Rename user pinky to reddy
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
rename: reddy
state: renamed
register: result
failed_when: not result.changed or result.failed
- name: Rename user pinky to reddy, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
rename: reddy
state: renamed
register: result
failed_when: not result.failed or "No user 'pinky'" not in result.msg
- name: Rename user reddy to reddy
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: reddy
rename: reddy
state: renamed
register: result
failed_when: result.changed or result.failed
- name: Rename user reddy back to pinky
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: reddy
rename: pinky
state: renamed
register: result
failed_when: not result.changed or result.failed
- name: User pinky absent and preserved for future exclusion.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
preserve: yes
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User pinky absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User pinky absent and preserved, when already absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
preserve: yes
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure user with GECOS information exists.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: igagarin
first: Iuri
last: Gagarin
gecos: Юрий Алексеевич Гагарин
register: result
failed_when: not result.changed or result.failed
- name: Ensure user with GECOS information exists, again.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: igagarin
first: Iuri
last: Gagarin
gecos: Юрий Алексеевич Гагарин
register: result
failed_when: result.changed or result.failed
- name: Modify GECOS information.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: igagarin
gecos: Юрий Гагарин
register: result
failed_when: not result.changed or result.failed
- name: Updating with existent data, should not change user.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: igagarin
first: Iuri
last: Gagarin
gecos: Юрий Гагарин
register: result
failed_when: result.changed or result.failed
- name: Ensure GECOS parameter is cleared.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: igagarin
gecos: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure GECOS parameter is cleared, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: igagarin
gecos: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure GECOS parameter cannot be used with state absent.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: igagarin
gecos: Юрий Гагарин
state: absent
register: result
failed_when: not result.failed or "Argument 'gecos' can not be used with action 'user' and state 'absent'" not in result.msg
- name: Ensure user igagarin is absent.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: igagarin
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure user with non-ascii name exists.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: igagarin
first: Юрий
last: Гагарин
register: result
failed_when: not result.changed or result.failed
- name: Ensure user with non-ascii name exists has proper GECOS value.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: igagarin
gecos: Юрий Гагарин
register: result
failed_when: result.changed or result.failed
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: manager1,manager2,manager3,pinky,pinky2,igagarin
state: absent
ansible-freeipa-master/tests/user/test_user_client_context.yml 0000664 0000000 0000000 00000002377 14600563364 0025377 0 ustar 00root root 0000000 0000000 ---
- name: Test user
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test user using client context, in client host.
ansible.builtin.import_playbook: test_user.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test user using client context, in server host.
ansible.builtin.import_playbook: test_user.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-master/tests/user/test_user_empty_lists.yml 0000664 0000000 0000000 00000005104 14600563364 0024720 0 ustar 00root root 0000000 0000000 ---
- name: Test users
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
tasks:
# SETUP
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
state: absent
- name: Ensure user testuser is present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
first: test
last: user
userauthtype: password,radius,otp
sshpubkey:
# yamllint disable-line rule:line-length
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqmVDpEX5gnSjKuv97AyzOhaUMMKz8ahOA3GY77tVC4o68KNgMCmDSEG1/kOIaElngNLaCha3p/2iAcU9Bi1tLKUlm2bbO5NHNwHfRxY/3cJtq+/7D1vxJzqThYwI4F9vr1WxyY2+mMTv3pXbfAJoR8Mu06XaEY5PDetlDKjHLuNWF+/O7ZU8PsULTa1dJZFrtXeFpmUoLoGxQBvlrlcPI1zDciCSU24t27Zan5Py2l5QchyI7yhCyMM77KDtj5+AFVpmkb9+zq50rYJAyFVeyUvwjzErvQrKJzYpA0NyBp7vskWbt36M16/M/LxEK7HA6mkcakO3ESWx5MT1LAjvdlnxbWG3787MxweHXuB8CZU+9bZPFBaJ+VQtOfJ7I8eH0S16moPC4ak8FlcFvOH8ERDPWLFDqfy09yaZ7bVIF0//5ZI7Nf3YDe3S7GrBX5ieYuECyP6UNkTx9BRsAQeVvXEc6otzB7iCSnYBMGUGzCqeigoAWaVQUONsSR3Uatks= pinky@ipaserver.el81.local # noqa 204
# TESTS - action: user
- name: Ensure user testuser present with empty sshpubkey
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
sshpubkey: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure user testuser present with empty sshpubkey, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
sshpubkey: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure user testuser present with empty userauthtype
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
userauthtype: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure user testuser present with empty userauthtype, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
userauthtype: ""
register: result
failed_when: result.changed or result.failed
# CLEANUP
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
state: absent
ansible-freeipa-master/tests/user/test_user_empty_string_params.yml 0000664 0000000 0000000 00000010733 14600563364 0026437 0 ustar 00root root 0000000 0000000 ---
- name: Test user
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
# CLEANUP TEST ITEMS
- name: Ensure user testuser absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
state: absent
# CREATE TEST ITEMS
- name: Ensure user testuser present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
first: test
last: user
register: result
failed_when: not result.changed or result.failed
# TESTS
- name: Ensure user testuser present with userauthtype password,radius,otp
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
userauthtype: password,radius,otp
register: result
failed_when: not result.changed or result.failed
- name: Ensure user testuser present with userauthtype password,radius,otp, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
userauthtype: password,radius,otp
register: result
failed_when: result.changed or result.failed
- name: Ensure user testuser present with empty userauthtype
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
userauthtype: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure user testuser present with empty userauthtype, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
userauthtype: ""
register: result
failed_when: result.changed or result.failed
- name: Ensure user testuser present with sshpubkey
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
sshpubkey:
# yamllint disable-line rule:line-length
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqmVDpEX5gnSjKuv97AyzOhaUMMKz8ahOA3GY77tVC4o68KNgMCmDSEG1/kOIaElngNLaCha3p/2iAcU9Bi1tLKUlm2bbO5NHNwHfRxY/3cJtq+/7D1vxJzqThYwI4F9vr1WxyY2+mMTv3pXbfAJoR8Mu06XaEY5PDetlDKjHLuNWF+/O7ZU8PsULTa1dJZFrtXeFpmUoLoGxQBvlrlcPI1zDciCSU24t27Zan5Py2l5QchyI7yhCyMM77KDtj5+AFVpmkb9+zq50rYJAyFVeyUvwjzErvQrKJzYpA0NyBp7vskWbt36M16/M/LxEK7HA6mkcakO3ESWx5MT1LAjvdlnxbWG3787MxweHXuB8CZU+9bZPFBaJ+VQtOfJ7I8eH0S16moPC4ak8FlcFvOH8ERDPWLFDqfy09yaZ7bVIF0//5ZI7Nf3YDe3S7GrBX5ieYuECyP6UNkTx9BRsAQeVvXEc6otzB7iCSnYBMGUGzCqeigoAWaVQUONsSR3Uatks= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: not result.changed or result.failed
- name: Ensure user testuser present with sshpubkey, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
sshpubkey:
# yamllint disable-line rule:line-length
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqmVDpEX5gnSjKuv97AyzOhaUMMKz8ahOA3GY77tVC4o68KNgMCmDSEG1/kOIaElngNLaCha3p/2iAcU9Bi1tLKUlm2bbO5NHNwHfRxY/3cJtq+/7D1vxJzqThYwI4F9vr1WxyY2+mMTv3pXbfAJoR8Mu06XaEY5PDetlDKjHLuNWF+/O7ZU8PsULTa1dJZFrtXeFpmUoLoGxQBvlrlcPI1zDciCSU24t27Zan5Py2l5QchyI7yhCyMM77KDtj5+AFVpmkb9+zq50rYJAyFVeyUvwjzErvQrKJzYpA0NyBp7vskWbt36M16/M/LxEK7HA6mkcakO3ESWx5MT1LAjvdlnxbWG3787MxweHXuB8CZU+9bZPFBaJ+VQtOfJ7I8eH0S16moPC4ak8FlcFvOH8ERDPWLFDqfy09yaZ7bVIF0//5ZI7Nf3YDe3S7GrBX5ieYuECyP6UNkTx9BRsAQeVvXEc6otzB7iCSnYBMGUGzCqeigoAWaVQUONsSR3Uatks= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: result.changed or result.failed
- name: Ensure user testuser present with empty sshpubkey
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
sshpubkey: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure user testuser present with empty sshpubkey, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
sshpubkey: ""
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure user testuser absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
state: absent
ansible-freeipa-master/tests/user/test_user_idp_attrs.yml 0000664 0000000 0000000 00000005704 14600563364 0024343 0 ustar 00root root 0000000 0000000 ---
- name: Test user
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: false
gather_facts: false
module_defaults:
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
tasks:
- name: Include tasks ../env_freeipa_facts.yml
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
# CLEANUP TEST ITEMS
- name: Ensure user idpuser is absent
ipauser:
name: idpuser
state: absent
# CREATE TEST ITEMS
- name: Run tests if FreeIPA 4.10.0+ is installed
when: ipa_version is version('4.10.0', '>=')
block:
- name: Ensure IDP provider is present
# TODO: Use an ansible-freeipa plugin instead of 'shell'
ansible.builtin.shell:
cmd: |
kinit -c test_krb5_cache admin <<< SomeADMINpassword
KRB5CCNAME=test_krb5_cache ipa idp-add keycloak --provider keycloak \
--org master \
--base-url https://client.ipademo.local:8443/auth \
--client-id ipa_oidc_client \
--secret <<< $(echo -e "Secret123\nSecret123")
kdestroy -c test_krb5_cache -q -A
register: addidp
failed_when:
- '"Added Identity Provider" not in addidp.stdout'
- '"already exists" not in addidp.stderr'
# TESTS
- name: Ensure user idpuser is present
ipauser:
name: idpuser
first: IDP
last: User
userauthtype: idp
idp: keycloak
idp_user_id: "idpuser@ipademo.local"
register: result
failed_when: not result.changed or result.failed
- name: Ensure user idpuser is present again
ipauser:
name: idpuser
first: IDP
last: User
userauthtype: idp
idp: keycloak
idp_user_id: "idpuser@ipademo.local"
register: result
failed_when: result.changed or result.failed
- name: Clear 'idp_user_id'
ipauser:
name: idpuser
idp_user_id: ""
register: result
failed_when: not result.changed or result.failed
- name: Clear 'idp'
ipauser:
name: idpuser
idp: ""
register: result
failed_when: not result.changed or result.failed
- name: Ensure user idpuser is absent
ipauser:
name: idpuser
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure user idpuser is absent again
ipauser:
name: idpuser
state: absent
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure IDP provider is absent
# TODO: Use an ansible-freeipa plugin instead of 'shell'
ansible.builtin.shell:
cmd: |
kinit -c test_krb5_cache admin <<< SomeADMINpassword
ipa idp-del keycloak
kdestroy -c test_krb5_cache -q -A
always:
- name: Ensure user idpuser is absent
ipauser:
name: idpuser
state: absent
ansible-freeipa-master/tests/user/test_user_random.yml 0000664 0000000 0000000 00000004516 14600563364 0023632 0 ustar 00root root 0000000 0000000 ---
- name: Test ipauser random password generation
hosts: ipaserver
become: true
tasks:
- name: Users user1 and user2 absent
ipauser:
ipaadmin_password: SomeADMINpassword
name:
- user1
- user2
state: absent
- name: User user1 present with random password
ipauser:
ipaadmin_password: SomeADMINpassword
name: user1
first: first1
last: last1
random: yes
update_password: on_create
register: ipauser
failed_when: not ipauser.changed or
ipauser.user.randompassword is not defined or
ipauser.failed
- name: Print generated random password
ansible.builtin.debug:
var: ipauser.user.randompassword
- name: User user1 absent
ipauser:
ipaadmin_password: SomeADMINpassword
name:
- user1
state: absent
- name: User user1 is present with random password using users parameter
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
first: first1
last: last1
random: yes
update_password: on_create
register: ipauser
failed_when: not ipauser.changed or
ipauser.user.user1.randompassword is not defined or
ipauser.failed
- name: User user1 absent
ipauser:
ipaadmin_password: SomeADMINpassword
name:
- user1
state: absent
- name: Users user1 and user2 present with random password
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
first: first1
last: last1
random: yes
- name: user2
first: first2
last: last2
random: yes
update_password: on_create
register: ipauser
failed_when: not ipauser.changed or
ipauser.user.user1.randompassword is not defined or
ipauser.user.user2.randompassword is not defined or
ipauser.failed
- name: Print generated random password for user1
ansible.builtin.debug:
var: ipauser.user.user1.randompassword
- name: Print generated random password for user2
ansible.builtin.debug:
var: ipauser.user.user2.randompassword
- name: Users user1 and user2 absent
ipauser:
ipaadmin_password: SomeADMINpassword
name:
- user1
- user2
state: absent
ansible-freeipa-master/tests/user/test_user_smb_attrs.yml 0000664 0000000 0000000 00000020653 14600563364 0024350 0 ustar 00root root 0000000 0000000 ---
- name: Test users
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
tasks:
- name: Set FreeIPA environment facts.
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
- name: Only run tests for IPA 4.8.0+
when: ipa_version is version('4.8.0', '>=')
block:
# SETUP
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
state: absent
# TESTS
- name: Ensure user testuser exists with all smb paramters
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
first: test
last: user
smb_profile_path: "/some/profile/path"
smb_home_dir: "/some/home/dir"
smb_home_drive: "U{{ ':' }}"
smb_logon_script: "/some/profile/script.sh"
register: result
failed_when: not result.changed or result.failed
- name: Ensure user testuser exists all smb paramters, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
first: test
last: user
smb_logon_script: "/some/profile/script.sh"
smb_profile_path: "/some/profile/path"
smb_home_dir: "/some/home/dir"
smb_home_drive: "U{{ ':' }}"
register: result
failed_when: result.changed or result.failed
- name: Check SMB logon script is correct
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_logon_script: "/some/profile/script.sh"
register: result
check_mode: true
failed_when: result.changed or result.failed
- name: Check SMB profile path is correct
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_profile_path: "/some/profile/path"
register: result
check_mode: true
failed_when: result.changed or result.failed
- name: Check SMB Home Directory is correct
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_home_dir: "/some/home/dir"
register: result
check_mode: true
failed_when: result.changed or result.failed
- name: Check SMB Home Drive is correct
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
first: test
last: user
smb_home_drive: "U{{ ':' }}"
register: result
check_mode: true
failed_when: result.changed or result.failed
- name: Set SMB logon script
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_logon_script: "/some/profile/another_script.sh"
register: result
failed_when: not result.changed or result.failed
- name: Set SMB logon script, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_logon_script: "/some/profile/another_script.sh"
register: result
failed_when: result.changed or result.failed
- name: Clear SMB logon script
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_logon_script: ""
register: result
failed_when: not result.changed or result.failed
- name: Clear SMB logon script, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_logon_script: ""
register: result
failed_when: result.changed or result.failed
- name: Set SMB profile path
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_profile_path: "/some/profile/another_path"
register: result
failed_when: not result.changed or result.failed
- name: Set SMB profile path, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_profile_path: "/some/profile/another_path"
register: result
failed_when: result.changed or result.failed
- name: Clear SMB profile path
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_profile_path: ""
register: result
failed_when: not result.changed or result.failed
- name: Clear SMB profile, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_profile_path: ""
register: result
failed_when: result.changed or result.failed
- name: Set SMB home directory
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_home_dir: "/some/other/home"
register: result
failed_when: not result.changed or result.failed
- name: Set SMB home directory, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_home_dir: "/some/other/home"
register: result
failed_when: result.changed or result.failed
- name: Clear SMB home directory
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_home_dir: ""
register: result
failed_when: not result.changed or result.failed
- name: Clear SMB home directory, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_home_dir: ""
register: result
failed_when: result.changed or result.failed
- name: Set SMB home drive
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_home_drive: "Z{{ ':' }}"
register: result
failed_when: not result.changed or result.failed
- name: Set SMB home drive, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_home_drive: "Z{{ ':' }}"
register: result
failed_when: result.changed or result.failed
- name: Set SMB home drive to invalid value
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_home_drive: "INVALID:"
register: result
failed_when: not result.failed or "value of smb_home_drive must be one of" not in result.msg
- name: Clear SMB home drive
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_home_drive: ""
register: result
failed_when: not result.changed or result.failed
- name: Clear SMB home drive, again
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
smb_home_drive: ""
register: result
failed_when: result.changed or result.failed
always:
# CLEANUP
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testuser
state: absent
ansible-freeipa-master/tests/user/test_users.yml 0000664 0000000 0000000 00000033745 14600563364 0022463 0 ustar 00root root 0000000 0000000 ---
- name: Test users
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
name: manager1,manager2,manager3,pinky,pinky2,mod1,mod2
state: absent
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
name: user1,user2,user3,user4,user5,user6,user7,user8,user9,user10
state: absent
- name: Users user1..10 present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
givenname: user1
last: Last
- name: user2
first: user2
last: Last
- name: user3
first: user3
last: Last
- name: user4
first: user4
last: Last
- name: user5
first: user5
last: Last
- name: user6
first: user6
last: Last
- name: user7
first: user7
last: Last
- name: user8
first: user8
last: Last
- name: user9
first: user9
last: Last
- name: user10
first: user10
last: Last
register: result
failed_when: not result.changed or result.failed
- name: Users user1..10 present, again
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
givenname: user1
sn: Last
- name: user2
first: user2
last: Last
- name: user3
first: user3
last: Last
- name: user4
first: user4
last: Last
- name: user5
first: user5
last: Last
- name: user6
first: user6
last: Last
- name: user7
first: user7
last: Last
- name: user8
first: user8
last: Last
- name: user9
first: user9
last: Last
- name: user10
first: user10
last: Last
register: result
failed_when: result.changed or result.failed
- name: Rename users user1 and user2 to mod1 and mod1
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
rename: mod1
- name: user2
rename: mod2
state: renamed
register: result
failed_when: not result.changed or result.failed
- name: Rename users mod1 and mod2 to the same name
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: mod1
rename: mod1
- name: mod2
rename: mod2
state: renamed
register: result
failed_when: result.changed or result.failed
- name: Rename users mod1 and mod2 back to user1 and user2
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: mod1
rename: user1
- name: mod2
rename: user2
state: renamed
register: result
failed_when: not result.changed or result.failed
# failed_when: not result.failed has been added as this test needs to
# fail because two users with the same name should be added in the same
# task.
- name: Duplicate names in users failure test
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
givenname: user1
last: Last
- name: user2
first: user2
last: Last
- name: user3
first: user3
last: Last
- name: user3
first: user3
last: Last
register: result
failed_when: result.changed or not result.failed or "is used more than once" not in result.msg
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
name: user1,user2,user3,user4,user5,user6,user7,user8,user9,user10
state: absent
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
name: manager1,manager2,manager3,pinky,pinky2
state: absent
- name: User manager1 present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: manager1
first: Manager1
last: One1
- name: manager2
first: Manager2
last: One2
- name: manager3
first: Manager3
last: One3
register: result
failed_when: not result.changed or result.failed
- name: User pinky present
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
uid: 10001
gid: 100
phone: "+555123457"
email: pinky@acme.com
principalexpiration: "21220119235959"
passwordexpiration: "2122-01-19 23:59:59"
first: pinky
last: Acme
initials: pa
#password: foo2
principal: pa
random: yes
street: PinkyStreet
city: PinkyCity
userstate: PinkyState
postalcode: PinkyZip
mobile: "+555123458,+555123459"
pager: "+555123450,+555123451"
fax: "+555123452,+555123453"
orgunit: PinkyOrgUnit
manager: manager1,manager2
update_password: on_create
carlicense: PinkyCarLicense1,PinkyCarLicense2
# sshpubkey
userauthtype: password,radius,otp
userclass: PinkyUserClass
#radius: "http://some.link/"
#radiususer: PinkyRadiusUser
departmentnumber: "1234"
employeenumber: "0815"
employeetype: "PinkyExmployeeType"
preferredlanguage: "en"
# certificate
noprivate: yes
nomembers: false
#issuer: PinkyIssuer
#subject: PinkySubject
register: result
failed_when: not result.changed or result.failed
- name: Same user pinky present again
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
uid: 10001
gid: 100
phone: "+555123457"
email: pinky@acme.com
principalexpiration: "21220119235959"
passwordexpiration: "2122-01-19 23:59:59"
first: pinky
last: Acme
initials: pa
#password: foo2
principal: pa
random: yes
street: PinkyStreet
city: PinkyCity
userstate: PinkyState
postalcode: PinkyZip
mobile: "+555123458,+555123459"
pager: "+555123450,+555123451"
fax: "+555123452,+555123453"
orgunit: PinkyOrgUnit
manager: manager1,manager2
update_password: on_create
carlicense: PinkyCarLicense1,PinkyCarLicense2
# sshpubkey
userauthtype: password,radius,otp
userclass: PinkyUserClass
#radius: "http://some.link/"
#radiususer: PinkyRadiusUser
departmentnumber: "1234"
employeenumber: "0815"
employeetype: "PinkyExmployeeType"
preferredlanguage: "en"
# certificate
noprivate: yes
nomembers: false
#issuer: PinkyIssuer
#subject: PinkySubject
register: result
failed_when: result.changed or result.failed
- name: User pinky present with changed settings
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
first: pinky
last: Acme
manager: []
principal: []
sshpubkey:
# yamllint disable-line rule:line-length
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqmVDpEX5gnSjKuv97AyzOhaUMMKz8ahOA3GY77tVC4o68KNgMCmDSEG1/kOIaElngNLaCha3p/2iAcU9Bi1tLKUlm2bbO5NHNwHfRxY/3cJtq+/7D1vxJzqThYwI4F9vr1WxyY2+mMTv3pXbfAJoR8Mu06XaEY5PDetlDKjHLuNWF+/O7ZU8PsULTa1dJZFrtXeFpmUoLoGxQBvlrlcPI1zDciCSU24t27Zan5Py2l5QchyI7yhCyMM77KDtj5+AFVpmkb9+zq50rYJAyFVeyUvwjzErvQrKJzYpA0NyBp7vskWbt36M16/M/LxEK7HA6mkcakO3ESWx5MT1LAjvdlnxbWG3787MxweHXuB8CZU+9bZPFBaJ+VQtOfJ7I8eH0S16moPC4ak8FlcFvOH8ERDPWLFDqfy09yaZ7bVIF0//5ZI7Nf3YDe3S7GrBX5ieYuECyP6UNkTx9BRsAQeVvXEc6otzB7iCSnYBMGUGzCqeigoAWaVQUONsSR3Uatks= pinky@ipaserver.el81.local # noqa 204
# yamllint disable-line rule:line-length
- AAAAB3NzaC1yc2EAAAADAQABAAABgQDc8MIjaSrxLYHvu+hduoF4m6NUFSlXZWzYbd3BK4L47/U4eiXoOS6dcfuZJDjmLfOipc7XVp7NADwAgA1yBOAjbeVpXr2tC8w8saZibl75WBOEjDfNroiOh/f/ojrwwHg05QTVSZHs27sU1HBPyCQM/FHVM6EnRfmyiBkEBA/3ca0PJ9UJhWb2XisCaz6y6QcTh4gQnvHzgmEmK31GwiKnmBSEQuj8P5NGCO8RlN3cq3zpRpMDEoBRCjQYicllf/5P43r5OGvS1LhTiAMfyqE37URezNQa7aozBpH1GhIwAmjAtm84jXQjxUgZPYC0aSLuADYErScOP4792r6koH9t/DM5/M+jG2c4PNWynDczUw6Eaxl5E3hU0Ee9UN0Oee7iBnVenS/QMeZNyo5lMA/HXT5lrYiJGTYM0shRjGXXYBbJZhWerguSWDAdUd1gvuGP1nb7/+/Cvb46+HX7zYouS5Ojo0yPzMZ07X142jnKAfx9LnKdMUCwBJzbtoJ91Zc= pinky@ipaserver.el81.local # noqa 204
register: result
failed_when: not result.changed or result.failed
- name: User pinky add manager manager1
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
manager: manager1
action: member
register: result
failed_when: not result.changed or result.failed
- name: User pinky add manager manager1 again
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
manager: manager1
action: member
register: result
failed_when: result.changed or result.failed
- name: User pinky add manager manager2, manager3
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
manager: manager2,manager3
action: member
register: result
failed_when: not result.changed or result.failed
- name: User pinky add manager manager2, manager3 again
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
manager: manager2,manager3
action: member
register: result
failed_when: result.changed or result.failed
- name: User pinky remove manager manager1
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
manager: manager1
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User pinky remove manager manager1 again
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
manager: manager1
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User pinky add principal pa
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
principal: pa
action: member
register: result
failed_when: not result.changed or result.failed
- name: User pinky add principal pa again
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
principal: pa
action: member
register: result
failed_when: result.changed or result.failed
- name: User pinky add principal pa1
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
principal: pa1
action: member
register: result
failed_when: not result.changed or result.failed
- name: User pinky remove principal pa1
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
principal: pa1
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User pinky remove principal pa1 again
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
principal: pa1
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User pinky remove principal pa
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
principal: pa
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User pinky remove principal non-existing pa2
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
principal: pa2
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: User pinky absent and preserved
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
preserve: yes
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User pinky absent and preserved, again
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
preserve: yes
state: absent
register: result
failed_when: result.changed or result.failed
- name: User pinky undeleted (preserved before)
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: undeleted
register: result
failed_when: not result.changed or result.failed
- name: User pinky undeleted (preserved before), again
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: undeleted
register: result
failed_when: result.changed or result.failed
- name: Users pinky disabled
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: disabled
register: result
failed_when: not result.changed or result.failed
- name: Users pinky disabled, again
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: disabled
register: result
failed_when: result.changed or result.failed
- name: User pinky enabled
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: enabled
register: result
failed_when: not result.changed or result.failed
- name: User pinky enabled, again
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
state: enabled
register: result
failed_when: result.changed or result.failed
- name: User pinky absent and preserved for future exclusion.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
preserve: yes
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User pinky absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
state: absent
register: result
failed_when: not result.changed or result.failed
- name: User pinky absent and preserved, when already absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: pinky
preserve: yes
state: absent
register: result
failed_when: result.changed or result.failed
- name: Remove test users
ipauser:
ipaadmin_password: SomeADMINpassword
name: manager1,manager2,manager3,pinky,pinky2
state: absent
ansible-freeipa-master/tests/user/test_users_absent.yml 0000664 0000000 0000000 00000001162 14600563364 0024003 0 ustar 00root root 0000000 0000000 ---
- name: Include create_users_json.yml
ansible.builtin.import_playbook: create_users_json.yml
- name: Test users absent
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include users.json
ansible.builtin.include_vars:
file: users.json # noqa missing-import
- name: Create dict with user names
ansible.builtin.set_fact:
user_names: "{{ user_names | default([]) + [{'name': item.name}] }}"
loop: "{{ users }}"
- name: Users absent len:{{ users | length }}
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ user_names }}"
state: absent
ansible-freeipa-master/tests/user/test_users_invalid_cert.yml 0000664 0000000 0000000 00000003331 14600563364 0025172 0 ustar 00root root 0000000 0000000 ---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Generate self-signed certificates.
ansible.builtin.shell:
cmd: |
openssl req -x509 -newkey rsa:2048 -days 365 -nodes -keyout "private{{ item }}.key" -out "cert{{ item }}.pem" -subj '/CN=test'
openssl x509 -outform der -in "cert{{ item }}.pem" -out "cert{{ item }}.der"
base64 "cert{{ item }}.der" -w5000 > "cert{{ item }}.b64"
with_items: [1, 2]
become: no
delegate_to: localhost
- name: User test absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
state: absent
- name: User test present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
first: test
last: test
- name: User test cert members present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: User test cert members absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certificate:
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Remove certificate files.
ansible.builtin.shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1, 2]
become: no
delegate_to: localhost
ansible-freeipa-master/tests/user/test_users_present.yml 0000664 0000000 0000000 00000000663 14600563364 0024214 0 ustar 00root root 0000000 0000000 ---
- name: Include create_users_json.yml
ansible.builtin.import_playbook: create_users_json.yml
- name: Test users present
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include users.json
ansible.builtin.include_vars:
file: users.json # noqa missing-import
- name: Users present len:{{ users | length }}
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ users }}"
ansible-freeipa-master/tests/user/test_users_present_slice.yml 0000664 0000000 0000000 00000001157 14600563364 0025372 0 ustar 00root root 0000000 0000000 ---
- name: Include create_users_json.yml
ansible.builtin.import_playbook: create_users_json.yml
- name: Test users present slice
hosts: ipaserver
become: true
gather_facts: false
vars:
slice_size: 500
tasks:
- name: Include users.json
ansible.builtin.include_vars:
file: users.json # noqa missing-import
- name: Size of users slice.
ansible.builtin.debug:
msg: "{{ users | length }}"
- name: Users present
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ users[item : item + slice_size] }}"
loop: "{{ range(0, users | length, slice_size) | list }}"
ansible-freeipa-master/tests/user/users.sh 0000664 0000000 0000000 00000001165 14600563364 0021224 0 ustar 00root root 0000000 0000000 #!/bin/bash -eu
NUM=${1-1000}
FILE="users.json"
date=$(date --date='+2 years' "+%Y-%m-%d %H:%M:%S")
echo "{" > "$FILE"
echo " \"users\": [" >> "$FILE"
for i in $(seq 1 "$NUM"); do
{
echo " {"
echo " \"name\": \"user$i\","
echo " \"first\": \"First $i\","
echo " \"last\": \"Last $i\","
echo " \"password\": \"user${i}PW\","
echo " \"passwordexpiration\": \"$date\""
} >> "$FILE"
if [ "$i" -lt "$NUM" ]; then
echo " }," >> "$FILE"
else
echo " }" >> "$FILE"
fi
done
echo " ]" >> "$FILE"
echo "}" >> "$FILE"
ansible-freeipa-master/tests/user/users_absent.sh 0000664 0000000 0000000 00000000566 14600563364 0022564 0 ustar 00root root 0000000 0000000 #!/bin/bash -eu
NUM=1000
FILE="users_absent.json"
echo "{" > "$FILE"
echo " \"users\": [" >> "$FILE"
for i in $(seq 1 "$NUM"); do
echo " {" >> "$FILE"
echo " \"name\": \"user$i\"," >> "$FILE"
if [ "$i" -lt "$NUM" ]; then
echo " }," >> "$FILE"
else
echo " }" >> "$FILE"
fi
done
echo " ]" >> "$FILE"
echo "}" >> "$FILE"
ansible-freeipa-master/tests/utils.py 0000664 0000000 0000000 00000024601 14600563364 0020263 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# Authors:
# Sergio Oliveira Campos
#
# Copyright (C) 2020 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
import os
import pytest
import re
import subprocess
import tempfile
import testinfra
from unittest import TestCase
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
def get_docker_env():
docker_env = os.getenv("RUN_TESTS_IN_DOCKER", None)
if docker_env in ["1", "True", "true", "yes", True]:
docker_env = "docker"
return docker_env
def get_ssh_password():
return os.getenv("IPA_SSH_PASSWORD")
def get_server_host():
return os.getenv("IPA_SERVER_HOST")
def get_disabled_test(group_name, test_name):
disabled_modules = [
disabled.strip()
for disabled in os.environ.get("IPA_DISABLED_MODULES", "").split(",")
]
disabled_tests = [
disabled.strip()
for disabled in os.environ.get("IPA_DISABLED_TESTS", "").split(",")
if disabled.strip()
]
if not any([disabled_modules, disabled_tests]):
return False
return group_name in disabled_modules or test_name in disabled_tests
def get_enabled_test(group_name, test_name):
enabled_modules = [
enabled.strip()
for enabled in os.environ.get("IPA_ENABLED_MODULES", "").split(",")
if enabled.strip()
]
enabled_tests = [
enabled.strip()
for enabled in os.environ.get("IPA_ENABLED_TESTS", "").split(",")
if enabled.strip()
]
if not any([enabled_modules, enabled_tests]):
return True
group_enabled = group_name in enabled_modules
test_enabled = test_name in enabled_tests
return group_enabled or test_enabled
def get_inventory_content():
"""Create the content of an inventory file for a test run."""
ipa_server_host = get_server_host()
container_engine = get_docker_env()
if container_engine is not None:
ipa_server_host += f" ansible_connection={container_engine}"
sshpass = get_ssh_password()
if sshpass:
ipa_server_host += " ansible_ssh_pass=%s" % sshpass
lines = [
"[ipaserver]",
ipa_server_host,
"[ipaserver:vars]",
"ipaserver_domain=test.local",
"ipaserver_realm=TEST.LOCAL",
]
return "\n".join(lines).encode("utf8")
def get_test_name_from_playbook_path(playbook):
"""
Create a test name based of a playbook path.
For example:
Input: /home/johndoe/ansible-freeipa/tests/dnszone/test_dnszone_mod.yml
Output: dnszone_test_dnszone_mod
"""
playbook_abspath = os.path.abspath(playbook)
playbook_rel_to_tests_dir = playbook_abspath.replace(SCRIPT_DIR, "")
playbook_slug = playbook_rel_to_tests_dir.strip("/").replace("/", "_")
return os.path.splitext(playbook_slug)[0]
def write_logs(result, test_name):
"""Write logs of a ansible run logs to `test/logs/`."""
log_dir = os.path.join(SCRIPT_DIR, "logs")
if not os.path.exists(log_dir):
os.makedirs(log_dir)
# Write stdout log for test
log_path = os.path.join(log_dir, "ansible_" + test_name + ".log")
with open(log_path, "w") as log_file:
log_file.write(result.stdout.decode("utf-8"))
# Write stderr log for test
error_log_path = os.path.join(log_dir, test_name + "-error.log")
with open(error_log_path, "w") as log_file:
log_file.write(result.stderr.decode("utf-8"))
def _run_playbook(playbook):
"""
Create a inventory using a temporary file and run ansible using it.
The logs of the run will be placed in `tests/logs/`.
"""
with tempfile.NamedTemporaryFile() as inventory_file:
inventory_file.write(get_inventory_content())
inventory_file.flush()
cmd_options = ["-i", inventory_file.name]
verbose = os.environ.get("IPA_VERBOSITY", None)
if verbose is not None:
cmd_options.append(verbose)
cmd = ["ansible-playbook"] + cmd_options + [playbook]
# pylint: disable=subprocess-run-check
process = subprocess.run(
cmd, cwd=SCRIPT_DIR, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
test_name = get_test_name_from_playbook_path(playbook)
write_logs(process, test_name)
return process
def run_playbook(playbook, allow_failures=False):
"""
Run an Ansible playbook and assert the return code.
Call ansible (using _run_playbook function) and assert the result of
the execution.
In case of failure the tail of the error message will be displayed
as an assertion message.
The full log of the execution will be available in the directory
`tests/logs/`.
"""
result = _run_playbook(playbook)
if allow_failures:
return result
status_code_msg = "ansible-playbook return code: {0}".format(
result.returncode
)
assert_msg = "\n".join(
[
"",
"-" * 30 + " Captured stdout " + "-" * 30,
result.stdout.decode("utf8"),
"-" * 30 + " Captured stderr " + "-" * 30,
result.stderr.decode("utf8"),
"-" * 30 + " Playbook Return Code " + "-" * 30,
status_code_msg,
]
)
# Need to get the last bytes of msg otherwise Azure
# will cut it out.
assert result.returncode == 0, assert_msg[-2500:]
return result
def list_test_yaml(dir_path):
"""
List the test playbooks inside a given directory.
A test playbook is any file inside the directory which the name starts with
`test_` and the extension is `.yml`.
"""
yamls = []
for root, _dirs, files in os.walk(dir_path):
for yaml_name in files:
if yaml_name.startswith("test_") and yaml_name.endswith(".yml"):
test_yaml_path = os.path.join(root, yaml_name)
yamls.append(
{
"path": test_yaml_path,
"name": yaml_name.split(".")[0],
}
)
return yamls
def get_test_playbooks():
"""
Get playbook tests grouped by first level directory.
This function visits the first level of directories inside `tests/` and
look for ansible playbooks on them.
Returns a dict with the directories found in `tests/` as key and a
list of test playbook files inside of it.
A test playbook is any file inside the directory which the name starts with
`test_` and the extension is `.yml`.
"""
test_dirs = os.listdir(SCRIPT_DIR)
groups = {}
for test_group_dir in sorted(test_dirs):
group_dir_path = os.path.join(SCRIPT_DIR, test_group_dir)
if not os.path.isdir(group_dir_path):
continue
yamls = list_test_yaml(group_dir_path)
if yamls:
groups[test_group_dir] = yamls
return groups
def kinit_admin(host, admin="admin", password="SomeADMINpassword"):
return host.run_test("kinit " + admin + "<<< " + password)
def kdestroy(host):
return host.run_test("kdestroy -A")
class AnsibleFreeIPATestCase(TestCase):
def setUp(self):
container_engine = get_docker_env()
if container_engine:
protocol = f"{container_engine}://"
user = ""
ssh_identity_file = None
else:
protocol = "ssh://"
password = get_ssh_password() or ""
if password:
password = ":" + password
current_user = os.getenv("USER")
ansible_user = os.getenv("ANSIBLE_REMOTE_USER", current_user)
user = ansible_user + password + "@"
ssh_identity_file = os.getenv("ANSIBLE_PRIVATE_KEY_FILE", None)
host_connection_info = protocol + user + get_server_host()
self.master = testinfra.get_host(
host_connection_info, ssh_identity_file=ssh_identity_file,
)
@staticmethod
def run_playbook(playbook, allow_failures=False):
return run_playbook(playbook, allow_failures)
@staticmethod
def run_playbook_with_exp_msg(playbook, expected_msg):
result = run_playbook(playbook, allow_failures=True)
assert (
expected_msg in result.stdout.decode("utf8")
or
expected_msg in result.stderr.decode("utf8")
)
@staticmethod
def __is_text_on_data(text, data):
return re.search(text, data) is not None
def check_details(self, expected_output, cmd, extra_cmds=None):
cmd = "ipa " + cmd
if extra_cmds:
cmd += " " + " ".join(extra_cmds)
kinit_admin(self.master)
res = self.master.run(cmd)
if res.rc != 0:
for output in expected_output:
assert self.__is_text_on_data(output, res.stderr), (
f"\n{'='*40}\nExpected: {output}\n{'='*40}\n"
+ f"Output:\n{res.stderr}{'='*40}\n"
)
else:
for output in expected_output:
assert self.__is_text_on_data(output, res.stdout), (
f"\n{'='*40}\nExpected: {output}\n{'='*40}\n"
+ f"Output:\n{res.stdout}{'='*40}\n"
)
kdestroy(self.master)
def check_notexists(self, members, cmd, extra_cmds=None):
cmd = "ipa " + cmd
if extra_cmds:
cmd += " " + " ".join(extra_cmds)
kinit_admin(self.master)
res = self.master.run(cmd)
for member in members:
assert not self.__is_text_on_data(member, res.stdout), (
f"\n{'='*40}\nExpected: {member}\n{'='*40}\n"
+ f"Output:\n{res.stdout}{'='*40}\n"
)
kdestroy(self.master)
def mark_xfail_using_ansible_freeipa_version(self, version, reason):
package = self.master.package("ansible-freeipa")
if not package.is_installed:
return
if package.version == version:
pytest.xfail(reason)
ansible-freeipa-master/tests/vault/ 0000775 0000000 0000000 00000000000 14600563364 0017701 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/tests/vault/env_cleanup.yml 0000664 0000000 0000000 00000003217 14600563364 0022726 0 ustar 00root root 0000000 0000000 ---
# Tasks executed to clean up test environment for Vault module.
- name: Ensure user vaults are absent
ipavault:
ipaadmin_password: SomeADMINpassword
name:
- stdvault
- symvault
- asymvault
username: "{{ username }}"
state: absent
loop:
- admin
- user01
loop_control:
loop_var: username
- name: Ensure shared vaults are absent
ipavault:
ipaadmin_password: SomeADMINpassword
name:
- sharedvault
- svcvault
state: absent
- name: Ensure test users do not exist.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- user01
- user02
- user03
state: absent
- name: Ensure test groups do not exist.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: vaultgroup
state: absent
- name: Remove files from target host.
ansible.builtin.file:
path: "{{ ansible_facts['env'].HOME }}/{{ item }}"
state: absent
with_items:
- A_private.pem
- A_public.pem
- B_private.pem
- B_public.pem
- A_private.b64
- A_public.b64
- B_private.b64
- B_public.b64
- password.txt
- in.txt
- out.txt
- name: Remove files from controller.
ansible.builtin.file:
path: "{{ playbook_dir }}/{{ item }}"
state: absent
delegate_to: localhost
become: no
with_items:
- A_private.pem
- A_public.pem
- B_private.pem
- B_public.pem
- A_private.b64
- A_public.b64
- B_private.b64
- B_public.b64
ansible-freeipa-master/tests/vault/env_setup.yml 0000664 0000000 0000000 00000002777 14600563364 0022451 0 ustar 00root root 0000000 0000000 ---
# Tasks executed to ensure a sane environment to test IPA Vault module.
- name: Ensure environment is clean.
ansible.builtin.import_tasks: env_cleanup.yml
- name: Create private/public key pair.
ansible.builtin.shell:
cmd: |
openssl genrsa -out "{{ item }}private.pem" 2048
openssl rsa -in "{{ item }}private.pem" -outform PEM -pubout -out "{{ item }}public.pem"
base64 "{{ item }}public.pem" -w5000 > "{{ item }}public.b64"
base64 "{{ item }}private.pem" -w5000 > "{{ item }}private.b64"
delegate_to: localhost
become: no
with_items:
- A_
- B_
- name: Copy files to target host.
ansible.builtin.copy:
src: "{{ playbook_dir }}/{{ item }}"
dest: "{{ ansible_facts['env'].HOME }}/{{ item }}"
mode: 0644
with_items:
- A_private.pem
- A_public.pem
- B_private.pem
- B_public.pem
- A_private.b64
- A_public.b64
- B_private.b64
- B_public.b64
- password.txt
- in.txt
- name: Ensure vaultgroup exists.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: vaultgroup
- name: Ensure testing users exist.
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
users:
- name: user01
first: First
last: Start
- name: user02
first: Second
last: Middle
- name: user03
first: Third
last: Last
ansible-freeipa-master/tests/vault/in.txt 0000664 0000000 0000000 00000000016 14600563364 0021045 0 ustar 00root root 0000000 0000000 Another World. ansible-freeipa-master/tests/vault/password.txt 0000664 0000000 0000000 00000000022 14600563364 0022276 0 ustar 00root root 0000000 0000000 SomeVAULTpassword
ansible-freeipa-master/tests/vault/tasks_vault_members.yml 0000664 0000000 0000000 00000021762 14600563364 0024506 0 ustar 00root root 0000000 0000000 ---
# Tasks to test member management for Vault module.
- name: Setup testing environment.
ansible.builtin.import_tasks: env_setup.yml
- name: Ensure vault is present
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
vault_type: "{{ vault.vault_type }}"
register: result
failed_when: not result.changed or result.failed
when: vault.vault_type == 'standard'
- name: Ensure vault is present
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
vault_password: SomeVAULTpassword
vault_type: "{{ vault.vault_type }}"
register: result
failed_when: not result.changed or result.failed
when: vault.vault_type == 'symmetric'
- name: Ensure vault is present
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
vault_type: "{{ vault.vault_type }}"
public_key: "{{ lookup('file', 'A_private.b64') }}"
register: result
failed_when: not result.changed or result.failed
when: vault.vault_type == 'asymmetric'
- name: Ensure vault member user is present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
users:
- user02
register: result
failed_when: not result.changed or result.failed
- name: Ensure vault member user is present, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
users:
- user02
register: result
failed_when: result.changed or result.failed
- name: Ensure more vault member users are present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
users:
- admin
- user02
register: result
failed_when: not result.changed or result.failed
- name: Ensure vault member user is still present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
users:
- user02
register: result
failed_when: result.changed or result.failed
- name: Ensure vault users are absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
users:
- admin
- user02
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure vault users are absent, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
users:
- admin
- user02
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure vault user is absent, once more.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
users:
- admin
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure vault member group is present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
groups: vaultgroup
register: result
failed_when: not result.changed or result.failed
- name: Ensure vault member group is present, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
groups: vaultgroup
register: result
failed_when: result.changed or result.failed
- name: Ensure vault member group is absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
groups: vaultgroup
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure vault member group is absent, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
groups: vaultgroup
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure vault member service is present.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
services: "HTTP/{{ ansible_facts['fqdn'] }}"
register: result
failed_when: not result.changed or result.failed
- name: Ensure vault member service is present, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
services: "HTTP/{{ ansible_facts['fqdn'] }}"
register: result
failed_when: result.changed or result.failed
- name: Ensure vault member service is absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
services: "HTTP/{{ ansible_facts['fqdn'] }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure vault member service is absent, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
action: member
services: "HTTP/{{ ansible_facts['fqdn'] }}"
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure user03 is an owner of vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
owners: user03
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure user03 is an owner of vault, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
owners: user03
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure user03 is not owner of vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
owners: user03
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure user03 is not owner of vault, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
owners: user03
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure vaultgroup is an ownergroup of vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
ownergroups: vaultgroup
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure vaultgroup is an ownergroup of vault, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
ownergroups: vaultgroup
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure vaultgroup is not ownergroup of vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
ownergroups: vaultgroup
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure vaultgroup is not ownergroup of vault, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
ownergroups: vaultgroup
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure service is an owner of vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
ownerservices: "HTTP/{{ ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is an owner of vault, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
ownerservices: "HTTP/{{ ansible_facts['fqdn'] }}"
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure service is not owner of vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
ownerservices: "HTTP/{{ ansible_facts['fqdn'] }}"
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure service is not owner of vault, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
ownerservices: "HTTP/{{ ansible_facts['fqdn'] }}"
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure {{ vault.vault_type }} vault is absent
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure {{ vault.vault_type }} vault is absent, again
ipavault:
ipaadmin_password: SomeADMINpassword
name: "{{ vault.name }}"
state: absent
register: result
failed_when: result.changed or result.failed
- name: Cleanup testing environment.
ansible.builtin.import_tasks: env_cleanup.yml
ansible-freeipa-master/tests/vault/test_vault_asymmetric.yml 0000664 0000000 0000000 00000024002 14600563364 0025051 0 ustar 00root root 0000000 0000000 ---
- name: Test vault
hosts: ipaserver
become: true
# Need to gather facts for ansible_env.
gather_facts: true
tasks:
- name: Setup testing environment.
ansible.builtin.import_tasks: env_setup.yml
- name: Ensure asymmetric vault is present
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
vault_type: asymmetric
public_key: "{{ lookup('file', 'A_public.b64') }}"
register: result
failed_when: result.failed or not result.changed
- name: Ensure asymmetric vault is present, again
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
vault_type: asymmetric
public_key: "{{ lookup('file', 'A_public.b64') }}"
register: result
failed_when: result.failed or result.changed
- name: Archive data to asymmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
vault_data: SomeValue
register: result
failed_when: result.failed or not result.changed
- name: Retrieve data from asymmetric vault using key A.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
private_key: "{{ lookup('file', 'A_private.b64') }}"
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'SomeValue'
- name: Change asymmetric vault key to B.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
vault_type: asymmetric
public_key: "{{ lookup('file', 'B_public.b64') }}"
private_key: "{{ lookup('file', 'A_private.b64') }}"
register: result
failed_when: result.failed or not result.changed
- name: Retrieve data from asymmetric vault using key B.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
private_key: "{{ lookup('file', 'B_private.b64') }}"
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'SomeValue'
- name: Change asymmetric vault key to A, using key_file
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
vault_type: asymmetric
public_key_file: "{{ ansible_facts['env'].HOME }}/A_public.pem"
private_key: "{{ lookup('file', 'B_private.b64') }}"
register: result
failed_when: result.failed or not result.changed
- name: Retrieve data from asymmetric vault using key A, with key_file.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
private_key_file: "{{ ansible_facts['env'].HOME }}/A_private.pem"
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'SomeValue'
- name: Change asymmetric vault key to B key, using key_files
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
vault_type: asymmetric
public_key_file: "{{ ansible_facts['env'].HOME }}/B_public.pem"
private_key_file: "{{ ansible_facts['env'].HOME }}/A_private.pem"
register: result
failed_when: result.failed or not result.changed
- name: Retrieve data from asymmetric vault, using key B.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
private_key: "{{ lookup('file', 'B_private.b64') }}"
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'SomeValue'
- name: Change asymmetric vault key to A, without specifying vault_type.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
vault_type: asymmetric
public_key: "{{ lookup('file', 'A_public.b64') }}"
private_key: "{{ lookup('file', 'B_private.b64') }}"
register: result
failed_when: result.failed or not result.changed
- name: Change asymmetric vault key to B, with key files, without specifying vault_type.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
public_key_file: "{{ ansible_facts['env'].HOME }}/B_public.pem"
private_key_file: "{{ ansible_facts['env'].HOME }}/A_private.pem"
register: result
failed_when: result.failed or not result.changed
- name: Archive data to asymmetric vault, matching `no_log` field.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
vault_data: SomeADMINpassword
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from asymmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
private_key: "{{ lookup('file', 'B_private.b64') }}"
state: retrieved
register: result
failed_when: result.vault.data != 'SomeADMINpassword' or result.changed or result.failed
- name: Change data in asymmetric vault
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
data: Hello World.
register: result
failed_when: not result.changed or result.failed
- name: Retrieve changed data from asymmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
private_key: "{{ lookup('file', 'B_private.b64') }}"
state: retrieved
register: result
failed_when: result.vault.data != 'Hello World.' or result.changed or result.failed
- name: Retrieve data from asymmetric vault into file {{ ansible_facts['env'].HOME }}/data.txt.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
out: "{{ ansible_facts['env'].HOME }}/data.txt"
private_key: "{{ lookup('file', 'B_private.b64') }}"
state: retrieved
register: result
failed_when: result.changed or result.failed or (result.vault.data | default(false))
- name: Verify retrieved data.
ansible.builtin.slurp:
src: "{{ ansible_facts['env'].HOME }}/data.txt"
register: slurpfile
failed_when: slurpfile['content'] | b64decode != 'Hello World.'
- name: Archive data with non-ASCII characters to asymmetric vault
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
data: The world of π is half rounded.
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from asymmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
private_key: "{{ lookup('file', 'B_private.b64') }}"
state: retrieved
register: result
failed_when: result.vault.data != 'The world of π is half rounded.' or result.changed or result.failed
- name: Archive data in asymmetric vault, from file.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
vault_type: asymmetric
in: "{{ ansible_facts['env'].HOME }}/in.txt"
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from asymmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
private_key: "{{ lookup('file', 'B_private.b64') }}"
state: retrieved
register: result
failed_when: result.vault.data != 'Another World.' or result.changed or result.failed
- name: Archive data with single character to asymmetric vault
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
data: c
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from asymmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
private_key: "{{ lookup('file', 'B_private.b64') }}"
state: retrieved
register: result
failed_when: result.vault.data != 'c' or result.changed or result.failed
- name: Ensure asymmetric vault is absent
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure asymmetric vault is absent, again
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure asymmetric vault is present, with public key from file.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
public_key_file: "{{ ansible_facts['env'].HOME }}/B_public.pem"
vault_type: asymmetric
register: result
failed_when: not result.changed or result.failed
- name: Ensure asymmetric vault is present, with password from file, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
public_key_file: "{{ ansible_facts['env'].HOME }}/B_public.pem"
vault_type: asymmetric
register: result
failed_when: result.changed or result.failed
- name: Archive data to asymmetric vault
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
data: Hello World.
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from asymmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
private_key: "{{ lookup('file', 'B_private.b64') }}"
state: retrieved
register: result
failed_when: result.vault.data != 'Hello World.' or result.changed or result.failed
- name: Retrieve data from asymmetric vault, with password file.
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
private_key_file: "{{ ansible_facts['env'].HOME }}/B_private.pem"
state: retrieved
register: result
failed_when: result.vault.data != 'Hello World.' or result.changed or result.failed
- name: Ensure asymmetric vault is absent
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure asymmetric vault is absent, again
ipavault:
ipaadmin_password: SomeADMINpassword
name: asymvault
state: absent
register: result
failed_when: result.changed or result.failed
- name: Cleanup testing environment.
ansible.builtin.import_tasks: env_cleanup.yml
ansible-freeipa-master/tests/vault/test_vault_change_type.yml 0000664 0000000 0000000 00000023753 14600563364 0025176 0 ustar 00root root 0000000 0000000 ---
- name: Test vault
hosts: ipaserver
become: true
# Need to gather facts for ansible_env.
gather_facts: true
tasks:
- name: Setup testing environment.
ansible.builtin.import_tasks: env_setup.yml
- name: Ensure test_vault is absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
state: absent
- name: Create standard vault with no data archived.
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: standard
- name: Change from standard to asymmetric
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: asymmetric
public_key: "{{ lookup('file', 'A_public.b64') }}"
register: result
failed_when: result.failed or not result.changed
- name: Change vault type from asymmetric to symmetric
vars:
krb5ccname: verify_change_from_asymmetric
block:
- name: Change from asymmetric to symmetric
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: symmetric
private_key: "{{ lookup('file', 'A_private.b64') }}"
password: SomeVAULTpassword
register: result
failed_when: result.failed or not result.changed
- name: Verify assymetric-only fields are not present.
ansible.builtin.shell: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa vault-show test_vault
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: result.failed or "Public Key:" in result.stdout
- name: Change vault type from symmetric to standard
vars:
krb5ccname: verify_change_from_symmetric
block:
- name: Change from symmetric to standard
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: standard
password: SomeVAULTpassword
register: result
failed_when: result.failed or not result.changed
- name: Verify salt is not present.
ansible.builtin.shell: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa vault-show test_vault
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: result.failed or "Salt:" in result.stdout
- name: Change from standard to symmetric
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: symmetric
password: SomeVAULTpassword
register: result
failed_when: result.failed or not result.changed
- name: Change vault type from symmetric to asymmetric
vars:
krb5ccname: verify_change_from_symmetric
block:
- name: Change from symmetric to asymmetric
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: asymmetric
password: SomeVAULTpassword
public_key: "{{ lookup('file', 'A_public.b64') }}"
register: result
failed_when: result.failed or not result.changed
- name: Verify salt is not present.
ansible.builtin.shell: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa vault-show test_vault
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: result.failed or "Salt:" in result.stdout
- name: Change vault type from asymmetric to standard
vars:
krb5ccname: verify_change_from_asymmetric
block:
- name: Change from asymmetric to standard
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: standard
private_key: "{{ lookup('file', 'A_private.b64') }}"
register: result
failed_when: result.failed or not result.changed
- name: Verify assymetric-only fields are not present.
ansible.builtin.shell: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa vault-show test_vault
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: result.failed or "Public Key:" in result.stdout
- name: Ensure test_vault is absent.
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
state: absent
- name: Create standard vault with data archived.
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: standard
data: hello
- name: Change from standard to asymmetric, with data
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: asymmetric
public_key: "{{ lookup('file', 'A_public.b64') }}"
register: result
failed_when: result.failed or not result.changed
- name: Retrieve data from asymmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
private_key: "{{ lookup('file', 'A_private.b64') }}"
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'hello'
- name: Change vault type from asymmetric to symmetric, with data
vars:
krb5ccname: verify_change_from_asymmetric
block:
- name: Change from asymmetric to symmetric, with data
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: symmetric
private_key: "{{ lookup('file', 'A_private.b64') }}"
password: SomeVAULTpassword
register: result
failed_when: result.failed or not result.changed
- name: Verify assymetric-only fields are not present.
ansible.builtin.shell: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa vault-show test_vault
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: result.failed or "Public Key:" in result.stdout
- name: Retrieve data from symmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
password: SomeVAULTpassword
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'hello'
- name: Change vault type from symmetric to standard, with data
vars:
krb5ccname: verify_change_from_symmetric
block:
- name: Change from symmetric to standard, with data
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: standard
password: SomeVAULTpassword
register: result
failed_when: result.failed or not result.changed
- name: Verify salt is not present.
ansible.builtin.shell: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa vault-show test_vault
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: result.failed or "Salt:" in result.stdout
- name: Retrieve data from standard vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'hello'
- name: Change from standard to symmetric, with data
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: symmetric
password: SomeVAULTpassword
register: result
failed_when: result.failed or not result.changed
- name: Retrieve data from symmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
state: retrieved
password: SomeVAULTpassword
register: result
failed_when: result.failed or result.changed or result.vault.data != 'hello'
- name: Change vault type from symmetric to asymmetric, with data
vars:
krb5ccname: verify_change_from_symmetric
block:
- name: Change from symmetric to asymmetric, with data
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: asymmetric
password: SomeVAULTpassword
public_key: "{{ lookup('file', 'A_public.b64') }}"
register: result
failed_when: result.failed or not result.changed
- name: Verify salt is not present.
ansible.builtin.shell: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa vault-show test_vault
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: result.failed or "Salt:" in result.stdout
- name: Retrieve data from asymmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
state: retrieved
private_key: "{{ lookup('file', 'A_private.b64') }}"
register: result
failed_when: result.failed or result.changed or result.vault.data != 'hello'
- name: Change vault type from asymmetric to standard, with data
vars:
krb5ccname: verify_change_from_asymmetric
block:
- name: Change from asymmetric to standard, with data
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
vault_type: standard
private_key: "{{ lookup('file', 'A_private.b64') }}"
register: result
failed_when: result.failed or not result.changed or result.failed
- name: Verify assymetric-only fields are not present.
ansible.builtin.shell: |
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin
KRB5CCNAME={{ krb5ccname }} ipa vault-show test_vault
kdestroy -A -q -c {{ krb5ccname }}
register: result
failed_when: result.failed or "Public Key:" in result.stdout
- name: Retrieve data from standard vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'hello'
- name: Remove test_vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: test_vault
state: absent
- name: Cleanup testing environment.
ansible.builtin.import_tasks: env_cleanup.yml
ansible-freeipa-master/tests/vault/test_vault_client_context.yml 0000664 0000000 0000000 00000001421 14600563364 0025716 0 ustar 00root root 0000000 0000000 ---
- name: Test vault
hosts: ipaserver
become: no
# Need to gather facts for ansible_env.
gather_facts: yes
tasks:
- name: Setup testing environment.
ansible.builtin.import_tasks: env_setup.yml
# vault requires 'ipaapi_context: client', and uses this
# context by defoult, so we test only for the case where
# 'ipaapi_context: server' is explicitly set.
- name: Execute with server context.
ipavault:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
name: ThisShouldNotWork
vault_type: standard
register: result
failed_when: not (result.failed and result.msg is regex("Context 'server' for ipavault not yet supported."))
- name: Cleanup testing environment.
ansible.builtin.import_tasks: env_cleanup.yml
ansible-freeipa-master/tests/vault/test_vault_members.yml 0000664 0000000 0000000 00000001017 14600563364 0024327 0 ustar 00root root 0000000 0000000 ---
- name: Test vault
hosts: ipaserver
become: true
# Need to gather facts for ansible_env.
gather_facts: true
tasks:
- name: Test vault module member operations.
ansible.builtin.include_tasks:
file: tasks_vault_members.yml
apply:
tags:
- "{{ vault.vault_type }}"
loop_control:
loop_var: vault
loop:
- { name: "stdvault", vault_type: "standard" }
- { name: "symvault", vault_type: "symmetric" }
- { name: "asymvault", vault_type: "asymmetric" }
ansible-freeipa-master/tests/vault/test_vault_standard.yml 0000664 0000000 0000000 00000010344 14600563364 0024500 0 ustar 00root root 0000000 0000000 ---
- name: Test vault
hosts: ipaserver
become: true
# Need to gather facts for ansible_env.
gather_facts: true
tasks:
- name: Setup testing environment.
ansible.builtin.import_tasks: env_setup.yml
- name: Ensure standard vault is present
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
vault_type: standard
register: result
failed_when: not result.changed or result.failed
- name: Ensure standard vault is present, again
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
vault_type: standard
register: result
failed_when: result.changed or result.failed
- name: Archive data to standard vault, matching `no_log` field.
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
vault_data: SomeADMINpassword
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from standard vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
state: retrieved
register: result
failed_when: result.vault.data != 'SomeADMINpassword' or result.changed or result.failed
- name: Archive data to standard vault
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
vault_data: Hello World.
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from standard vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
state: retrieved
register: result
failed_when: result.vault.data != 'Hello World.' or result.changed or result.failed
- name: Retrieve data from standard vault into file {{ ansible_facts['env'].HOME }}/data.txt.
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
out: "{{ ansible_facts['env'].HOME }}/data.txt"
state: retrieved
register: result
failed_when: result.changed or result.failed or (result.vault.data | default(false))
- name: Verify retrieved data.
ansible.builtin.slurp:
src: "{{ ansible_facts['env'].HOME }}/data.txt"
register: slurpfile
failed_when: slurpfile['content'] | b64decode != 'Hello World.'
- name: Archive data with non-ASCII characters to standard vault
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
vault_data: The world of π is half rounded.
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from standard vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
state: retrieved
register: result
failed_when: result.vault.data != 'The world of π is half rounded.' or result.changed or result.failed
- name: Archive data in standard vault, from file.
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
vault_type: standard
in: "{{ ansible_facts['env'].HOME }}/in.txt"
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from standard vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
state: retrieved
register: result
failed_when: result.vault.data != 'Another World.' or result.changed or result.failed
- name: Archive data with single character to standard vault
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
vault_data: c
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from standard vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
state: retrieved
register: result
failed_when: result.vault.data != 'c' or result.changed or result.failed
- name: Ensure standard vault is absent
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure standard vault is absent, again
ipavault:
ipaadmin_password: SomeADMINpassword
name: stdvault
state: absent
register: result
failed_when: result.changed or result.failed
- name: Cleanup testing environment.
ansible.builtin.import_tasks: env_cleanup.yml
ansible-freeipa-master/tests/vault/test_vault_symmetric.yml 0000664 0000000 0000000 00000026300 14600563364 0024713 0 ustar 00root root 0000000 0000000 ---
- name: Test vault
hosts: ipaserver
become: true
# Need to gather facts for ansible_env.
gather_facts: true
tasks:
- name: Setup testing environment.
ansible.builtin.import_tasks: env_setup.yml
- name: Ensure symmetric vault is present
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
vault_type: symmetric
password: SomeVAULTpassword
register: result
failed_when: not result.changed or result.failed
- name: Ensure symmetric vault is present, again
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
vault_type: symmetric
password: SomeVAULTpassword
register: result
failed_when: result.changed or result.failed
- name: Archive data to symmetric vault, matching `no_log` field.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
vault_data: SomeADMINpassword
password: SomeVAULTpassword
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from symmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
state: retrieved
register: result
failed_when: result.changed or result.failed or result.vault.data != 'SomeADMINpassword'
- name: Archive data to symmetric vault
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
vault_data: Hello World.
password: SomeVAULTpassword
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from symmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
state: retrieved
register: result
failed_when: result.changed or result.failed or result.vault.data != 'Hello World.'
- name: Retrieve data from symmetric vault into file {{ ansible_facts['env'].HOME }}/data.txt.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
out: "{{ ansible_facts['env'].HOME }}/data.txt"
state: retrieved
register: result
failed_when: result.changed or result.failed or (result.vault.data | default(false))
- name: Verify retrieved data.
ansible.builtin.slurp:
src: "{{ ansible_facts['env'].HOME }}/data.txt"
register: slurpfile
failed_when: slurpfile['content'] | b64decode != 'Hello World.'
- name: Archive data with non-ASCII characters to symmetric vault
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
vault_data: The world of π is half rounded.
register: result
failed_when: result.failed or not result.changed
- name: Retrieve data from symmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'The world of π is half rounded.'
- name: Archive data in symmetric vault, from file.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
in: "{{ ansible_facts['env'].HOME }}/in.txt"
password: SomeVAULTpassword
register: result
failed_when: result.failed or not result.changed
- name: Retrieve data from symmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'Another World.'
- name: Archive data with single character to symmetric vault
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
vault_data: c
register: result
failed_when: result.failed or not result.changed
- name: Retrieve data from symmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'c'
- name: Ensure symmetric vault is absent
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure symmetric vault is absent, again
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
state: absent
register: result
failed_when: result.failed or result.changed
- name: Ensure symmetric vault is present, with password from file.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: user01
password_file: "{{ ansible_facts['env'].HOME }}/password.txt"
vault_type: symmetric
register: result
failed_when: result.failed or not result.changed
- name: Ensure symmetric vault is present, with password from file, again.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
username: user01
password_file: "{{ ansible_facts['env'].HOME }}/password.txt"
vault_type: symmetric
register: result
failed_when: result.failed or result.changed
- name: Archive data to symmetric vault
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
vault_data: Hello World.
password: SomeVAULTpassword
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from symmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'Hello World.'
- name: Retrieve data from symmetric vault, with password file.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password_file: "{{ ansible_facts['env'].HOME }}/password.txt"
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'Hello World.'
- name: Retrieve data from symmetric vault, with wrong password.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeWRONGpassword
state: retrieved
register: result
failed_when: result.changed or not result.failed or "Invalid credentials" not in result.msg
- name: Change vault password.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
new_password: SomeNEWpassword
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from symmetric vault, with new password.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeNEWpassword
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'Hello World.'
- name: Retrieve data from symmetric vault, with old password.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
state: retrieved
register: result
failed_when: not result.failed or "Invalid credentials" not in result.msg
- name: Change symmetric vault salt, changing password
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeNEWpassword
new_password: SomeVAULTpassword
salt: AAAAAAAAAAAAAAAAAAAAAAA=
register: result
failed_when: result.failed or not result.changed
- name: Change symmetric vault salt, without changing password
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
new_password: SomeVAULTpassword
salt: MTIzNDU2Nzg5MDEyMzQ1Ngo=
register: result
failed_when: result.failed or not result.changed
- name: Try to change symmetric vault salt, without providing any password
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
salt: MTIzNDU2Nzg5MDEyMzQ1Ngo=
register: result
failed_when: not result.failed and "Vault `salt` can only change when changing the password." not in result.msg
- name: Try to change symmetric vault salt, without providing `password`
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
salt: MTIzNDU2Nzg5MDEyMzQ1Ngo=
new_password: SomeVAULTpassword
register: result
failed_when: not result.failed and "Vault `salt` can only change when changing the password." not in result.msg
- name: Try to change symmetric vault salt, without providing `new_password`
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
salt: MTIzNDU2Nzg5MDEyMzQ1Ngo=
password: SomeVAULTpassword
register: result
failed_when: not result.failed and "Vault `salt` can only change when changing the password." not in result.msg
- name: Try to change symmetric vault salt, using wrong password.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeWRONGpassword
new_password: SomeWRONGpassword
salt: MDEyMzQ1Njc4OTAxMjM0NQo=
register: result
failed_when: not result.failed
- name: Ensure symmetric vault is absent
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Ensure symmetric vault is absent, again
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
state: absent
register: result
failed_when: result.failed or result.changed
- name: Try to change password of inexistent vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: inexistentvault
password: SomeVAULTpassword
new_password: SomeNEWpassword
register: result
failed_when: not result.failed or "Cannot modify password of inexistent vault" not in result.msg
- name: Ensure symmetric vault is present
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
vault_type: symmetric
password: APasswordToChange
vault_data: Hello World.
register: result
failed_when: not result.changed or result.failed
- name: Change symmetric vault password, using password file.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: APasswordToChange
new_password_file: "{{ ansible_facts['env'].HOME }}/password.txt"
vault_type: symmetric
register: result
failed_when: not result.changed or result.failed
- name: Retrieve data from symmetric vault.
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
password: SomeVAULTpassword
state: retrieved
register: result
failed_when: result.failed or result.changed or result.vault.data != 'Hello World.'
- name: Ensure symmetric vault is absent
ipavault:
ipaadmin_password: SomeADMINpassword
name: symvault
state: absent
register: result
failed_when: result.failed or not result.changed
- name: Cleanup testing environment.
ansible.builtin.import_tasks: env_cleanup.yml
ansible-freeipa-master/utils/ 0000775 0000000 0000000 00000000000 14600563364 0016544 5 ustar 00root root 0000000 0000000 ansible-freeipa-master/utils/ansible-doc-test 0000775 0000000 0000000 00000012714 14600563364 0021634 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2020 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
import os
import os.path
import sys
import argparse
import subprocess
def run_ansible_doc(role, module, verbose=False):
playbook_dir, module_path = get_playbook_dir(role, module)
module_dir = os.path.dirname(module_path)
doc_fragments = os.path.dirname(module_path)+"/../doc_fragments/"
command = ["env",
"ANSIBLE_LIBRARY=%s" % module_dir,
"ANSIBLE_DOC_FRAGMENT_PLUGINS=%s" % doc_fragments,
"ansible-doc",
"--playbook-dir=%s" % playbook_dir,
"--type=module",
"-vvv",
module]
process = subprocess.run(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout = process.stdout.decode("utf8")
stderr = process.stderr.decode("utf8")
if process.returncode != 0 or "WARNING" in stderr:
print("%s\n%s" % (module_path, stderr))
print("%s\n%s" % (module_path, stdout))
return 1
elif verbose == 1:
print(module_path)
elif verbose > 1:
print("%s\n%s" % (module_path, stdout))
return 0
def get_playbook_dir(role, module):
if module is None:
raise IOError("module is not set")
if role is not None:
playbook_dir = "roles/%s" % role
module_path = "%s/library/%s" % (playbook_dir, module)
if not os.path.isfile(module_path):
raise IOError("No module '%s' in role '%s'" % (module, role))
else:
playbook_dir = "."
module_path = "plugins/modules/%s" % module
if not os.path.isfile(module_path):
raise IOError("No module '%s'" % module)
return playbook_dir, module_path
def ansible_doc_test(path, verbose):
role = None
module = None
only_roles = False
only_modules = False
if path is not None:
if path.startswith("roles/") and len(path) > 6:
_path = path[6:].split("/")
role = _path[0]
if len(_path) == 2 and _path[1] == "":
pass
elif len(_path) == 3 and _path[1] == "library":
module = _path[2]
if module == "":
module = None
elif len(_path) > 1:
# Ignore other paths
return 0
elif path in ["roles", "roles/"]:
# roles only
only_roles = True
elif path.startswith("plugins/modules/") and len(path) > 16:
_path = path[16:].split("/")
if len(_path) == 1:
module = _path[0]
else:
# Ignore other paths
return 0
elif path in ["plugins", "plugins/",
"plugins/modules", "plugins/modules/"]:
only_modules = True
else:
# Ignore other paths
return 0
errors = 0
try:
if role and not os.path.isdir("roles/%s" % role):
raise IOError("No role '%s'" % role)
if module:
errors += run_ansible_doc(role, module, verbose)
elif role:
# All modules in role
modules = os.listdir("roles/%s/library" % role)
for _module in modules:
if _module.endswith(".py"):
errors += run_ansible_doc(role, _module, verbose)
else:
if not only_modules:
# All roles and plugins
roles = os.listdir("roles/")
for _role in roles:
if (
not os.path.isdir("roles/%s" % _role)
or not os.path.isdir("roles/%s/library" % _role)
):
continue
modules = os.listdir("roles/%s/library" % _role)
for _module in modules:
if _module.endswith(".py"):
errors += run_ansible_doc(_role, _module, verbose)
if not only_roles:
modules = os.listdir("plugins/modules")
for _module in modules:
if _module.endswith(".py"):
errors += run_ansible_doc(None, _module, verbose)
except IOError as e:
print(str(e))
errors += 1
return errors
usage = "Usage: ansible-doc-test [options] [path]"
parser = argparse.ArgumentParser(usage=usage)
parser.add_argument("-v", dest="verbose", action="count",
help="increase output verbosity", default=0)
options, args = parser.parse_known_args()
errors = 0
for arg in args:
errors += ansible_doc_test(arg, options.verbose)
if len(args) == 0:
errors += ansible_doc_test(None, options.verbose)
if errors != 0:
sys.exit(1)
ansible-freeipa-master/utils/ansible-freeipa.spec.in 0000664 0000000 0000000 00000014240 14600563364 0023054 0 ustar 00root root 0000000 0000000 # Turn off automatic python byte compilation because these are Ansible
# roles and the files are transferred to the node and compiled there with
# the python version used in the node
%define __brp_python_bytecompile %{nil}
%global python %{__python3}
Summary: Roles and playbooks to deploy FreeIPA servers, replicas and clients
Name: ansible-freeipa
Version: @@VERSION@@
Release: @@RELEASE@@%{?dist}
URL: https://github.com/freeipa/ansible-freeipa
License: GPL-3.0-or-later
Source: %{name}-%{version}-@@RELEASE@@.tar.bz2
BuildArch: noarch
%description
Ansible roles to install and uninstall FreeIPA servers, replicas and clients,
roles for backups and SmartCard configuration, modules for management and also
playbooks for all roles and modules.
Note: The Ansible playbooks and roles require a configured Ansible environment
where the Ansible nodes are reachable and are properly set up to have an IP
address and a working package manager.
Features
- Server, replica and client deployment
- Cluster deployments: Server, replicas and clients in one playbook
- One-time-password (OTP) support for client installation
- Repair mode for clients
- Backup and restore, also to and from controller
- Smartcard setup for servers and clients
- Modules for automembership rule management
- Modules for automount key management
- Modules for automount location management
- Modules for automount map management
- Modules for certificate management
- Modules for config management
- Modules for delegation management
- Modules for dns config management
- Modules for dns forwarder management
- Modules for dns record management
- Modules for dns zone management
- Modules for group management
- Modules for hbacrule management
- Modules for hbacsvc management
- Modules for hbacsvcgroup management
- Modules for host management
- Modules for hostgroup management
- Modules for idoverridegroup management
- Modules for idoverrideuser management
- Modules for idp management
- Modules for idrange management
- Modules for idview management
- Modules for location management
- Modules for netgroup management
- Modules for permission management
- Modules for privilege management
- Modules for pwpolicy management
- Modules for role management
- Modules for self service management
- Modules for server management
- Modules for service management
- Modules for service delegation rule management
- Modules for service delegation target management
- Modules for sudocmd management
- Modules for sudocmdgroup management
- Modules for sudorule management
- Modules for topology management
- Modules for trust management
- Modules for user management
- Modules for vault management
Supported FreeIPA Versions
FreeIPA versions 4.6 and up are supported by all roles.
The client role supports versions 4.4 and up, the server role is working with
versions 4.5 and up, the replica role is currently only working with versions
4.6 and up.
Supported Distributions
- RHEL/CentOS 7.4+
- Fedora 26+
- Ubuntu
- Debian 10+ (ipaclient only, no server or replica!)
Requirements
Controller
- Ansible version: 2.13+
- /usr/bin/kinit is required on the controller if a one time password (OTP)
is used
Node
- Supported FreeIPA version (see above)
- Supported distribution (needed for package installation only, see above)
Limitations
External signed CA is now supported. But the currently needed two step process
is an issue for the processing in a simple playbook.
Work is planned to have a new method to handle CSR for external signed CAs in
a separate step before starting the server installation.
%package tests
Summary: ansible-freeipa tests
Requires: %{name} = %{version}-%{release}
%description tests
ansible-freeipa tests.
Please have a look at %{_datadir}/ansible-freeipa/requirements-tests.txt
to get the needed requrements to run the tests.
%prep
%setup -q -n ansible-freeipa-%{version}-@@RELEASE@@
# Do not create backup files with patches
# Fix python modules and module utils:
# - Remove shebang
# - Remove execute flag
for i in roles/ipa*/library/*.py roles/ipa*/module_utils/*.py plugins/*/*.py;
do
sed -i '1{/\/usr\/bin\/python*/d;}' $i
chmod a-x $i
done
for i in utils/*.py utils/new_module utils/changelog utils/ansible-doc-test;
do
sed -i '{s@/usr/bin/env python*@%{python}@}' $i
done
%build
%install
install -m 755 -d %{buildroot}%{_datadir}/ansible/roles/
cp -rp roles/ipaserver %{buildroot}%{_datadir}/ansible/roles/
cp -rp roles/ipaserver/README.md README-server.md
cp -rp roles/ipareplica %{buildroot}%{_datadir}/ansible/roles/
cp -rp roles/ipareplica/README.md README-replica.md
cp -rp roles/ipaclient %{buildroot}%{_datadir}/ansible/roles/
cp -rp roles/ipaclient/README.md README-client.md
cp -rp roles/ipabackup %{buildroot}%{_datadir}/ansible/roles/
cp -rp roles/ipabackup/README.md README-backup.md
cp -rp roles/ipasmartcard_server %{buildroot}%{_datadir}/ansible/roles/
cp -rp roles/ipasmartcard_server/README.md README-smartcard_server.md
cp -rp roles/ipasmartcard_client %{buildroot}%{_datadir}/ansible/roles/
cp -rp roles/ipasmartcard_client/README.md README-smartcard_client.md
install -m 755 -d %{buildroot}%{_datadir}/ansible/plugins/
cp -rp plugins/* %{buildroot}%{_datadir}/ansible/plugins/
install -m 755 -d %{buildroot}%{_datadir}/ansible-freeipa
cp requirements*.txt %{buildroot}%{_datadir}/ansible-freeipa/
cp -rp utils %{buildroot}%{_datadir}/ansible-freeipa/
install -m 755 -d %{buildroot}%{_datadir}/ansible-freeipa/tests
cp -rp tests %{buildroot}%{_datadir}/ansible-freeipa/
%files
%license COPYING
%{_datadir}/ansible/roles/ipaserver
%{_datadir}/ansible/roles/ipareplica
%{_datadir}/ansible/roles/ipaclient
%{_datadir}/ansible/roles/ipabackup
%{_datadir}/ansible/roles/ipasmartcard_server
%{_datadir}/ansible/roles/ipasmartcard_client
%{_datadir}/ansible/plugins/doc_fragments
%{_datadir}/ansible/plugins/module_utils
%{_datadir}/ansible/plugins/modules
%doc README*.md
%doc playbooks
%{_datadir}/ansible-freeipa/requirements.txt
%{_datadir}/ansible-freeipa/requirements-dev.txt
%{_datadir}/ansible-freeipa/utils
%files tests
%{_datadir}/ansible-freeipa/tests
%{_datadir}/ansible-freeipa/requirements-tests.txt
%changelog
* @@DATE@@ Thomas Woerner - @@VERSION@@-@@RELEASE@@
- GIT version @@VERSION@@-@@RELEASE@@
ansible-freeipa-master/utils/build-galaxy-release.sh 0000775 0000000 0000000 00000015210 14600563364 0023102 0 ustar 00root root 0000000 0000000 #!/bin/bash -eu
#
# Build Ansible Collection from ansible-freeipa repo
#
prog=$(basename "$0")
pwd=$(pwd)
usage() {
cat < ]
Build Anible Collection for ansible-freeipa.
The namespace defaults to freeipa an name defaults to ansible_freeipa,
if namespace and name are not given. Namespace and name need to be set
together.
Options:
-a Add all files, no only files known to git repo
-k Keep build directory
-i Install the generated collection
-o Build offline without using git, using version A.B.C
Also enables -a
-p Installation the generated collection in the path, the
ansible_collections sub directory will be created and will
contain the collection: ansible_collections//
Also enables -i
-h Print this help
EOF
}
all=0
keep=0
install=0
path=
offline=
galaxy_version=
while getopts "ahkio:p:" arg; do
case $arg in
a)
all=1
;;
h)
usage
exit 0
;;
k)
keep=1
;;
i)
install=1
;;
o)
galaxy_version=$OPTARG
offline=1
all=1
;;
p)
path=$OPTARG
install=1
;;
\?)
echo
usage
exit 1
;;
esac
done
shift $((OPTIND-1))
if [ $# != 0 ] && [ $# != 2 ]; then
usage
exit 1
fi
namespace="${1-freeipa}"
name="${2-ansible_freeipa}"
if [ -z "$namespace" ]; then
echo "Namespace might not be empty"
exit 1
fi
if [ -z "$name" ]; then
echo "Name might not be empty"
exit 1
fi
collection_prefix="${namespace}.${name}"
[ -z "$galaxy_version" ] && \
galaxy_version=$(git describe --tags 2>/dev/null | sed -e "s/^v//")
if [ -z "$galaxy_version" ]; then
echo "Version could not be detected"
exit 1
fi
echo "Building collection: ${namespace}-${name}-${galaxy_version}"
GALAXY_BUILD=".galaxy-build"
if [ -e "$GALAXY_BUILD" ]; then
echo "Removing existing $GALAXY_BUILD ..."
rm -rf "$GALAXY_BUILD"
echo -e "\033[ARemoving existing $GALAXY_BUILD ... \033[32;1mDONE\033[0m"
fi
mkdir "$GALAXY_BUILD"
echo "Copying files to build dir $GALAXY_BUILD ..."
if [ $all == 1 ]; then
# Copy all files except galaxy build dir
for file in .[A-z]* [A-z]*; do
[[ "$file" == "${GALAXY_BUILD}" ]] && continue
cp -a "$file" "${GALAXY_BUILD}/"
done
else
# git ls-tree is quoting, therefore ignore SC2046: Quote this to prevent
# word splitting
# shellcheck disable=SC2046
tar -cf - $(git ls-tree HEAD --name-only -r) | (cd "$GALAXY_BUILD/" && tar -xf -)
fi
echo -e "\033[ACopying files to build dir $GALAXY_BUILD ... \033[32;1mDONE\033[0m"
cd "$GALAXY_BUILD" || exit 1
sed -i -e "s/version: .*/version: \"$galaxy_version\"/" galaxy.yml
sed -i -e "s/namespace: .*/namespace: \"$namespace\"/" galaxy.yml
sed -i -e "s/name: .*/name: \"$name\"/" galaxy.yml
find . -name "*~" -exec rm {} \;
if [ $offline != 1 ]; then
echo "Creating CHANGELOG.rst..."
"$(dirname "$0")/changelog" --galaxy > CHANGELOG.rst
echo -e "\033[ACreating CHANGELOG.rst... \033[32;1mDONE\033[0m"
else
echo "Empty changelog, offline generated." > CHANGELOG.rst
fi
sed -i -e "s/ansible.module_utils.ansible_freeipa_module/ansible_collections.${collection_prefix}.plugins.module_utils.ansible_freeipa_module/" plugins/modules/*.py
python utils/create_action_group.py "meta/runtime.yml" "$collection_prefix"
(cd plugins/module_utils && {
ln -sf ../../roles/*/module_utils/*.py .
})
(cd plugins/modules && {
sed -i -e "s/ansible.module_utils.ansible_ipa_/ansible_collections.${collection_prefix}.plugins.module_utils.ansible_ipa_/" ../../roles/*/library/*.py
ln -sf ../../roles/*/library/*.py .
})
# There are no action plugins anymore in the roles, therefore this section
# is commneted out.
#[ ! -x plugins/action ] && mkdir plugins/action
#(cd plugins/action && {
# ln -sf ../../roles/*/action_plugins/*.py .
#})
for doc_fragment in plugins/doc_fragments/*.py; do
fragment=$(basename -s .py "$doc_fragment")
echo "Fixing doc fragments for ${fragment} in plugins/modules..."
for file in plugins/modules/*.py; do
sed -i -e "s/- ${fragment}/- ${collection_prefix}.${fragment}/" "$file"
done
echo -e "\033[AFixing doc framents for ${fragment} in plugins/modules... \033[32;1mDONE\033[0m"
done
echo "Fixing examples in plugins/modules..."
find plugins/modules -name "*.py" -print0 |
while IFS= read -d '' -r line; do
python utils/galaxyfy-module-EXAMPLES.py "$line" \
"ipa" "$collection_prefix"
done
echo -e "\033[AFixing examples in plugins/modules... \033[32;1mDONE\033[0m"
echo "Fixing examples in roles/*/library..."
find roles/*/library -name "*.py" -print0 |
while IFS= read -d '' -r line; do
python utils/galaxyfy-module-EXAMPLES.py "$line" \
"ipa" "$collection_prefix"
done
echo -e "\033[AFixing examples in roles/*/library... \033[32;1mDONE\033[0m"
echo "Fixing playbooks in roles/*/tasks..."
for line in roles/*/tasks/*.yml; do
python utils/galaxyfy-playbook.py "$line" "ipa" "$collection_prefix"
done
echo -e "\033[AFixing playbooks in roles/*tasks... \033[32;1mDONE\033[0m"
echo "Fixing playbooks in playbooks..."
find playbooks -name "*.yml" -print0 |
while IFS= read -d '' -r line; do
python utils/galaxyfy-playbook.py "$line" "ipa" "$collection_prefix"
done
echo -e "\033[AFixing playbooks in playbooks... \033[32;1mDONE\033[0m"
echo "Fixing README(s)..."
find . -name "README*.md" -print0 |
while IFS= read -d '' -r line; do
python utils/galaxyfy-README.py "$line" "ipa" "$collection_prefix"
done
echo -e "\033[AFixing examples in plugins/modules... \033[32;1mDONE\033[0m"
echo "Fixing playbooks in tests..."
find tests -name "*.yml" -print0 |
while IFS= read -d '' -r line; do
python utils/galaxyfy-playbook.py "$line" "ipa" "$collection_prefix"
done
echo -e "\033[AFixing playbooks in tests... \033[32;1mDONE\033[0m"
ansible-galaxy collection build --force --output-path="$pwd"
cd "$pwd" || exit 1
if [ $keep == 0 ]; then
echo "Removing build dir $GALAXY_BUILD ..."
rm -rf "$GALAXY_BUILD"
echo -e "\033[ARemoving build dir $GALAXY_BUILD ... \033[32;1mDONE\033[0m"
else
echo "Keeping build dir $GALAXY_BUILD"
fi
if [ $install == 1 ]; then
echo "Installing collection ${namespace}-${name}-${galaxy_version}.tar.gz ..."
ansible-galaxy collection install ${path:+"-p$path"} "${namespace}-${name}-${galaxy_version}.tar.gz" --force ${offline/1/--offline}
fi
ansible-freeipa-master/utils/build-srpm.sh 0000775 0000000 0000000 00000001047 14600563364 0021163 0 ustar 00root root 0000000 0000000 #!/bin/bash -eu
git_version=$(git describe --tags | sed -e "s/^v//")
version=${git_version%%-*}
release=${git_version#*-}
release=${release//-/_}
date=$(date "+%a %b %e %Y")
topdir=$(dirname "$0")
sed -e "s/@@VERSION@@/$version/g" -e "s/@@RELEASE@@/$release/g" -e "s/@@DATE@@/$date/g" "$topdir/ansible-freeipa.spec.in" > ansible-freeipa.spec
git archive --format=tar --prefix="ansible-freeipa-${version}-${release}/" 'HEAD' | bzip2 -c > "ansible-freeipa-${version}-${release}.tar.bz2"
rpmbuild --define "_sourcedir $PWD" -bs ansible-freeipa.spec
ansible-freeipa-master/utils/changelog 0000775 0000000 0000000 00000012325 14600563364 0020424 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2020 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
import sys
import argparse
import subprocess
class Ref:
def __init__(self, commit):
self.commit = commit
def store(commits, prs, authors, commit, author, merge, msg):
if commit is not None:
if msg[0].startswith("Merge pull request #"):
pr_ref = int(msg[0].split()[3][1:])
if len(msg) > 1:
prs[pr_ref] = msg[1].strip()
else:
prs[pr_ref] = Ref(merge)
else:
commits[commit] = msg[0].strip()
authors.setdefault(author, []).append(commit)
def get_commit(commits, commit):
_commits = [value for key, value in commits.items()
if key.startswith(commit)]
if len(_commits) == 1:
return _commits[0]
return commit
def get_output(command):
try:
ret = subprocess.check_output(command, shell=True)
ret = ret.decode("utf-8").strip()
except subprocess.CalledProcessError:
print("Command '%s' failed" % command)
sys.exit(1)
return ret
def changelog(tag):
prev_tag = None
if tag is not None and tag != "":
prev_tag = get_output(
"git describe --tag --abbrev=0 --always '%s^'" % tag)
else:
tag = get_output("git describe --tags --abbrev=0 "
"$(git rev-list --tags --max-count=1)")
version = tag[1:]
if prev_tag is not None:
command = ["git", "log", "%s..%s" % (prev_tag, tag)]
else:
command = ["git", "log", "%s.." % tag]
process = subprocess.run(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
if process.returncode != 0:
print("git log failed: %s" %
process.stderr.decode("utf8").split("\n")[0])
sys.exit(1)
lines = process.stdout.decode("utf-8").split("\n")
commits = {}
prs = {}
authors = {}
commit = None
author = None
merge = None
msg = None
for line in lines:
line = line.rstrip()
if line.startswith("commit "):
store(commits, prs, authors, commit, author, merge, msg)
author = None
msg = []
commit = line[7:]
elif line.startswith(" "):
msg.append(line[4:])
else:
try:
key, value = line.split(":", 1)
if key == "Author":
author = value.split("<")[0].strip()
elif key == "Merge":
merge = value.split()[1].strip()
# Ignore Date, ..
except ValueError:
pass
# Add final commit
if commit:
store(commits, prs, authors, commit, author, merge, msg)
if prev_tag is not None:
line = "Changes for %s since %s" % (version, prev_tag[1:])
else:
line = "Changes since %s" % version
print("%s" % line)
print("-" * len(line))
print()
prs_sorted = sorted(prs.keys(), reverse=True)
for pr_ref in prs_sorted:
if isinstance(prs[pr_ref], Ref):
msg = get_commit(commits, prs[pr_ref].commit)
else:
msg = prs[pr_ref]
print(" - %s (#%d)" % (msg, pr_ref))
print()
if prev_tag is not None:
line = "Detailed changelog for %s since %s by author" % (version,
prev_tag[1:])
else:
line = "Detailed changelog since %s by author" % version
print("%s" % line)
print("-" * len(line))
print(" %d authors, %d commits" % (len(authors), len(commits)))
print()
authors_sorted = sorted(authors.keys())
for author in authors_sorted:
print("%s (%d)\n" % (author, len(authors[author])))
for commit in authors[author]:
print(" - %s" % commits[commit])
print()
parser = argparse.ArgumentParser(usage="Usage: changelog [options]")
parser.add_argument("--tag", dest="tag", help="git tag")
parser.add_argument("--galaxy", dest="galaxy", action="store_true",
help="Create changelog for galaxy")
options, args = parser.parse_known_args()
if len(args) != 0:
parser.print_help()
sys.exit(1)
if options.galaxy:
# Get latest tag
tag = get_output("git describe --tag --abbrev=0")
# get number of commits since latest tag
count = get_output("git rev-list '%s'.. --count" % tag)
if count != "0":
changelog(None)
changelog(tag)
else:
changelog(options.tag)
ansible-freeipa-master/utils/check_test_configuration.py 0000775 0000000 0000000 00000010334 14600563364 0024165 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
"""Check which tests are scheduled to be executed."""
import sys
import re
import os
import yaml
RE_IS_TEST = re.compile(r"(.*/)?test_.*\.yml")
RE_IS_VARS = re.compile(r"(.*/)?variables(_.*)?\.yaml")
REPO_ROOT = os.path.join(os.path.dirname(__file__), "..")
def get_tests():
"""Retrieve a list of modules and its tests."""
def get_module(root):
if root != _test_dir:
while True:
module = os.path.basename(root)
root = os.path.dirname(root)
if root == _test_dir:
return module
return "."
_result = {}
_test_dir = os.path.join(REPO_ROOT, "tests")
for root, _dirs, files in os.walk(_test_dir):
module = get_module(root)
_result[module] = [
os.path.splitext(test)[0]
for test in files
if RE_IS_TEST.search(test)
]
return _result
def get_test_config(scenarios):
template_path = os.path.join(REPO_ROOT, "tests/azure/templates")
_result = {}
for _root, _dirs, files in os.walk(template_path):
for filename in [x for x in files if RE_IS_VARS.search(x)]:
_templates, *scenario = os.path.basename(
os.path.splitext(filename)[0]
).split("_", 1)
scenario = scenario[0] if scenario else "All"
_result[scenario] = {}
# only process selected scenarios
if scenario not in scenarios and len(scenarios) > 1:
continue
with open(os.path.join(template_path, filename), "rt") as inp:
data = yaml.safe_load(inp)
if not data["variables"].get("empty", False):
variables = data["variables"]
for key, value in variables.items():
variables[key] = [
x.strip() for x in value.split(",") if x.strip()
]
_result[scenario] = variables
return _result
def print_configuration(scenario, disabled, enabled):
"""Print the test configuration for a scenario."""
print(f"\nScenario: {scenario}")
for test_cfg, title in [(disabled, "Disabled"), (enabled, "Enabled")]:
print(f" {title} tests:")
if test_cfg:
for module, tests in test_cfg.items():
print(f" {module}:")
for test in tests:
print(f" - {test}")
else:
print(" No custom configuration.")
def main():
if any(item in sys.argv for item in ["-h", "--help"]):
print("usage: check_test_config.py [-h|--help] [SCENARIO...]")
return
scenarios = ["All"] + sys.argv[1:]
all_tests = get_tests()
test_config = get_test_config(scenarios)
print("Test configuration:")
for scenario in sorted(test_config.keys()):
if scenario not in scenarios and len(scenarios) > 1:
continue
# extract scenario configuration
config = test_config[scenario]
disabled = {}
enabled = {}
for res, state in [(disabled, "disabled"), (enabled, "enabled")]:
items = [
x.strip()
for x in
os.environ.get(f"ipa_{state}_modules".upper(), "").split(",")
if x.strip()
] if scenario == "All" else []
modules = config.get(f"ipa_{state}_modules", []) + items
for module in modules:
if module != "None":
res[module] = set(all_tests[module])
items = [
x.strip()
for x in
os.environ.get(f"ipa_{state}_tests".upper(), "").split(",")
if x.strip()
] if scenario == "All" else []
test_list = config.get(f"ipa_{state}_tests", []) + items
for test in test_list:
if test == "None":
continue
for module, tests in all_tests.items():
if test in tests:
mod = res.setdefault(module, set())
mod.add(test)
tests.remove(test)
print_configuration(scenario, disabled, enabled)
if __name__ == "__main__":
main()
ansible-freeipa-master/utils/create_action_group.py 0000664 0000000 0000000 00000001171 14600563364 0023132 0 ustar 00root root 0000000 0000000 import sys
import yaml
from facts import MANAGEMENT_MODULES
def create_action_group(yml_file, project_prefix):
yaml_data = None
with open(yml_file) as f_in:
yaml_data = yaml.safe_load(f_in)
yaml_data.setdefault("action_groups", {})[
"%s.modules" % project_prefix
] = MANAGEMENT_MODULES
with open(yml_file, 'w') as f_out:
yaml.safe_dump(yaml_data, f_out, default_flow_style=False,
explicit_start=True)
if len(sys.argv) != 3:
print("Usage: %s " % sys.argv[0])
sys.exit(-1)
create_action_group(sys.argv[1], sys.argv[2])
ansible-freeipa-master/utils/facts.py 0000664 0000000 0000000 00000002434 14600563364 0020221 0 ustar 00root root 0000000 0000000 import os
def get_roles(directory):
roles = []
_rolesdir = "%s/roles/" % directory
for _role in os.listdir(_rolesdir):
_roledir = "%s/%s" % (_rolesdir, _role)
if not os.path.isdir(_roledir) or \
not os.path.isdir("%s/meta" % _roledir) or \
not os.path.isdir("%s/tasks" % _roledir):
continue
roles.append(_role)
return sorted(roles)
def get_modules(directory):
management_modules = []
roles_modules = []
for root, _dirs, files in os.walk(directory):
if not root.startswith("%s/plugins/" % directory) and \
not root.startswith("%s/roles/" % directory):
continue
for _file in files:
if _file.endswith(".py"):
if root == "%s/plugins/modules" % directory:
management_modules.append(_file[:-3])
elif root.startswith("%s/roles/" % directory):
if root.endswith("/library"):
roles_modules.append(_file[:-3])
return sorted(management_modules), sorted(roles_modules)
BASE_DIR = os.path.abspath(os.path.dirname(__file__) + "/..")
ROLES = get_roles(BASE_DIR)
MANAGEMENT_MODULES, ROLES_MODULES = get_modules(BASE_DIR)
ALL_MODULES = sorted(MANAGEMENT_MODULES + ROLES_MODULES)
ansible-freeipa-master/utils/galaxyfy-README.py 0000664 0000000 0000000 00000003664 14600563364 0021706 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2020 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
import sys
from galaxyfy import galaxyfy_playbook
def readme(readme_in, project_prefix, collection_prefix):
out_lines = []
with open(readme_in) as in_f:
changed = False
code = False
code_lines = []
for line in in_f:
stripped = line.strip()
if stripped.startswith("```"):
if code:
_out_lines, _changed = \
galaxyfy_playbook(project_prefix, collection_prefix,
code_lines)
out_lines.extend(_out_lines)
code_lines = []
if _changed:
changed = True
code = False
else:
code = True
out_lines.append(line)
continue
if code:
code_lines.append(line)
else:
out_lines.append(line)
if changed:
with open(readme_in, "w") as out_f:
for line in out_lines:
out_f.write(line)
readme(sys.argv[1], sys.argv[2], sys.argv[3])
ansible-freeipa-master/utils/galaxyfy-module-EXAMPLES.py 0000664 0000000 0000000 00000004070 14600563364 0023442 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2020 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see