pax_global_header 0000666 0000000 0000000 00000000064 14232747165 0014525 g ustar 00root root 0000000 0000000 52 comment=ba3fe74b60bcfcc8140e32ed33d06bb3dd14b112
ansible-freeipa-v1.7.0/ 0000775 0000000 0000000 00000000000 14232747165 0014746 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/.ansible-lint 0000664 0000000 0000000 00000001163 14232747165 0017331 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
kinds:
- playbook: '**/tests/**/test_*.yml'
- playbook: '**/playbooks/**/*.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.
use_default_rules: true
verbosity: 1
ansible-freeipa-v1.7.0/.copr/ 0000775 0000000 0000000 00000000000 14232747165 0015767 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/.copr/Makefile 0000664 0000000 0000000 00000000410 14232747165 0017422 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-v1.7.0/.github/ 0000775 0000000 0000000 00000000000 14232747165 0016306 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/.github/workflows/ 0000775 0000000 0000000 00000000000 14232747165 0020343 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/.github/workflows/ansible-test.yml 0000664 0000000 0000000 00000000575 14232747165 0023467 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@v2
with:
fetch-depth: 0
- name: Install virtualenv using pip
run: pip install virtualenv
- name: Run ansible-test
run: bash tests/sanity/sanity.sh
ansible-freeipa-v1.7.0/.github/workflows/docs.yml 0000664 0000000 0000000 00000004130 14232747165 0022014 0 ustar 00root root 0000000 0000000 ---
name: Verify Ansible documentation.
on:
- push
- pull_request
jobs:
check_docs_29:
name: Check Ansible Documentation with Ansible 2.9.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install Ansible 2.9
run: |
python -m pip install "ansible < 2.10"
- name: Run ansible-doc-test
run: |
ANSIBLE_LIBRARY="." ANSIBLE_DOC_FRAGMENT_PLUGINS="." python utils/ansible-doc-test -v roles plugins
check_docs_2_11:
name: Check Ansible Documentation with ansible-core 2.11.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install Ansible 2.11
run: |
python -m pip install "ansible-core >=2.11,<2.12"
- name: Run ansible-doc-test
run: |
ANSIBLE_LIBRARY="." ANSIBLE_DOC_FRAGMENT_PLUGINS="." python utils/ansible-doc-test -v roles plugins
check_docs_2_12:
name: Check Ansible Documentation with ansible-core 2.12.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install Ansible 2.12
run: |
python -m pip install "ansible-core >=2.12,<2.13"
- name: Run ansible-doc-test
run: |
python -m pip install "ansible-core >=2.12,<2.13"
ANSIBLE_LIBRARY="." ANSIBLE_DOC_FRAGMENT_PLUGINS="." python utils/ansible-doc-test -v roles plugins
check_docs_latest:
name: Check Ansible Documentation with latest Ansible version.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
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-v1.7.0/.github/workflows/lint.yml 0000664 0000000 0000000 00000003734 14232747165 0022043 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@v2
- uses: actions/setup-python@v2
with:
python-version: "3.x"
- name: Run ansible-lint
run: |
pip install ansible-core==2.11.6 ansible-lint
find playbooks roles tests -name '*.yml' ! -name "env_*" ! -name "tasks_*" -exec ansible-lint --force-color {} \+
env:
ANSIBLE_MODULE_UTILS: plugins/module_utils
ANSIBLE_LIBRARY: plugins/modules
ANSIBLE_DOC_FRAGMENT_PLUGINS: plugins/doc_fragments
yamllint:
name: Verify yamllint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: "3.x"
- name: Run yaml-lint
uses: ibiqlik/action-yamllint@v1
pydocstyle:
name: Verify pydocstyle
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
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@v2
- uses: actions/setup-python@v2
with:
python-version: "3.x"
- name: Run flake8
run: |
pip install flake8
flake8
pylint:
name: Verify pylint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: "3.x"
- name: Run pylint
run: |
pip install pylint==2.12.2
pylint plugins roles --disable=import-error
shellcheck:
name: Shellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@1.1.0
ansible-freeipa-v1.7.0/.github/workflows/readme.yml 0000664 0000000 0000000 00000000642 14232747165 0022325 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@v2
- 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-v1.7.0/.gitignore 0000664 0000000 0000000 00000000111 14232747165 0016727 0 ustar 00root root 0000000 0000000 *.pyc
*.retry
# ignore virtual environments
/.tox/
/.venv/
tests/logs/
ansible-freeipa-v1.7.0/.pre-commit-config.yaml 0000664 0000000 0000000 00000002163 14232747165 0021231 0 ustar 00root root 0000000 0000000 ---
repos:
- repo: https://github.com/ansible/ansible-lint.git
rev: v5.3.2
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
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.26.1
hooks:
- id: yamllint
files: \.(yaml|yml)$
- repo: https://gitlab.com/pycqa/flake8
rev: 3.9.2
hooks:
- id: flake8
- repo: https://gitlab.com/pycqa/pydocstyle
rev: 6.1.1
hooks:
- id: pydocstyle
- repo: https://github.com/pycqa/pylint
rev: v2.12.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-v1.7.0/.yamllint 0000664 0000000 0000000 00000000552 14232747165 0016602 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-v1.7.0/CONTRIBUTING.md 0000664 0000000 0000000 00000010454 14232747165 0017203 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-v1.7.0/COPYING 0000664 0000000 0000000 00000104513 14232747165 0016005 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-v1.7.0/README-automember.md 0000664 0000000 0000000 00000017066 14232747165 0020375 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.8+
**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-v1.7.0/README-automountkey.md 0000664 0000000 0000000 00000005146 14232747165 0020775 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.8+
**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-v1.7.0/README-automountlocation.md 0000664 0000000 0000000 00000005065 14232747165 0022015 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.8+
**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-v1.7.0/README-automountmap.md 0000664 0000000 0000000 00000003775 14232747165 0020770 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.8+
**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"
```
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
`desc` \| `description` | Description of the map | yes
`state` | The state to ensure. It can be one of `present`, or `absent`, default: `present`. | no
Notes
=====
Creation of indirect mount points are not supported.
Authors
=======
Chris Procter
ansible-freeipa-v1.7.0/README-config.md 0000664 0000000 0000000 00000013410 14232747165 0017467 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.8+
**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
```
```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
```
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`, `disabled`). 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
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` |
All returned fields take the same form as their namesake input parameters
Authors
=======
Chris Procter
ansible-freeipa-v1.7.0/README-delegation.md 0000664 0000000 0000000 00000007124 14232747165 0020342 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.8+
**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-v1.7.0/README-dnsconfig.md 0000664 0000000 0000000 00000006622 14232747165 0020203 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.8+
**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-v1.7.0/README-dnsforwardzone.md 0000664 0000000 0000000 00000007444 14232747165 0021301 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.8+
**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-v1.7.0/README-dnsrecord.md 0000664 0000000 0000000 00000031744 14232747165 0020217 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.8+
**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-v1.7.0/README-dnszone.md 0000664 0000000 0000000 00000015067 14232747165 0017714 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.8+
**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 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
`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
ansible-freeipa-v1.7.0/README-group.md 0000664 0000000 0000000 00000011466 14232747165 0017367 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.
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.8+
**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
```
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
became: true
- 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 remove groups:
```yaml
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
# Remove goups sysops, appops and ops
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: sysops,appops,ops
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 group name strings. | no
`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
`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` or `absent`, default: `present`. | yes
Authors
=======
Thomas Woerner
ansible-freeipa-v1.7.0/README-hbacrule.md 0000664 0000000 0000000 00000010041 14232747165 0020004 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.8+
**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-v1.7.0/README-hbacsvc.md 0000664 0000000 0000000 00000004475 14232747165 0017646 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.8+
**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-v1.7.0/README-hbacsvcgroup.md 0000664 0000000 0000000 00000006744 14232747165 0020724 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.8+
**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-v1.7.0/README-host.md 0000664 0000000 0000000 00000030150 14232747165 0017177 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.8+
**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 location (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. choices: ["radius", "otp", "pkinit", "hardened", ""] | 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
| `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
Authors
=======
Thomas Woerner
ansible-freeipa-v1.7.0/README-hostgroup.md 0000664 0000000 0000000 00000010603 14232747165 0020255 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.8+
**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-v1.7.0/README-idrange.md 0000664 0000000 0000000 00000014164 14232747165 0017642 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.8+
**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
`dom_name` \| `ipanttrusteddomainname` | Name 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
`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-v1.7.0/README-location.md 0000664 0000000 0000000 00000003612 14232747165 0020035 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.8+
**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-v1.7.0/README-permission.md 0000664 0000000 0000000 00000012257 14232747165 0020422 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.8+
**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-v1.7.0/README-privilege.md 0000664 0000000 0000000 00000006630 14232747165 0020216 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.8+
**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-v1.7.0/README-pwpolicy.md 0000664 0000000 0000000 00000006077 14232747165 0020103 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.8+
**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
```
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) | no
`minlife` \| `krbminpwdlife` | Minimum password lifetime in hours. (int) | no
`history` \| `krbpwdhistorylength` | Password history size. (int) | no
`minclasses` \| `krbpwdmindiffchars` | Minimum number of character classes. (int) | no
`minlength` \| `krbpwdminlength` | Minimum length of password. (int) | no
`priority` \| `cospriority` | Priority of the policy, higher number means lower priority. (int) | no
`maxfail` \| `krbpwdmaxfailure` | Consecutive failures before lockout. (int) | no
`failinterval` \| `krbpwdfailurecountinterval` | Period after which failure count will be reset in seconds. (int) | no
`lockouttime` \| `krbpwdlockoutduration` | Period for which lockout is enforced in seconds. (int) | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | yes
Authors
=======
Thomas Woerner
ansible-freeipa-v1.7.0/README-role.md 0000664 0000000 0000000 00000012571 14232747165 0017172 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.8+
**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-v1.7.0/README-selfservice.md 0000664 0000000 0000000 00000006736 14232747165 0020551 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.8+
**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-v1.7.0/README-server.md 0000664 0000000 0000000 00000014270 14232747165 0017535 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.8+
**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 location string. Only in state: present. "" for location reset. | no
`service_weight` \| `ipaserviceweight` | Weight for server services. Type Values 0 to 65535, -1 for weight reset. Only in state: present. (int) | no
`hidden` | Set hidden state of a server. Only in state: present. (bool) | no
`no_members` | Suppress processing of membership attributes. Only in state: present. (bool) | no
`delete_continue` \| `continue` | Continuous mode: Don't stop on errors. Only in state: absent. (bool) | no
`ignore_last_of_role` | Skip a check whether the last CA master or DNS server is removed. Only in state: absent. (bool) | no
`ignore_topology_disconnect` | Ignore topology connectivity problems after removal. Only in state: absent. (bool) | no
`force` | Force server removal even if it does not exist. Will always result in changed. Only in 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-v1.7.0/README-service.md 0000664 0000000 0000000 00000025424 14232747165 0017672 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.8+
**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` or `hardened`. 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-v1.7.0/README-servicedelegationrule.md 0000664 0000000 0000000 00000011302 14232747165 0022604 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.8+
**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-v1.7.0/README-servicedelegationtarget.md 0000664 0000000 0000000 00000007331 14232747165 0023132 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.8+
**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-v1.7.0/README-sudocmd.md 0000664 0000000 0000000 00000004071 14232747165 0017663 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.8+
**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-v1.7.0/README-sudocmdgroup.md 0000664 0000000 0000000 00000006707 14232747165 0020750 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.8+
**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-v1.7.0/README-sudorule.md 0000664 0000000 0000000 00000010407 14232747165 0020067 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.8+
**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 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
`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-v1.7.0/README-topology.md 0000664 0000000 0000000 00000013006 14232747165 0020077 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.8+
**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-v1.7.0/README-trust.md 0000664 0000000 0000000 00000006346 14232747165 0017415 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.8+
**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-v1.7.0/README-user.md 0000664 0000000 0000000 00000030331 14232747165 0017201 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.8+
**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
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 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
```
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`, `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. | no
`last` \| `sn` | The last name string. | 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` | The UID integer. | no
`gid` \| `gidnumber` | The GID integer. | 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` | List of supported user authentication types. Choices: `password`, `radius`, `otp` and ``. 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
`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
`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
| `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
Authors
=======
Thomas Woerner
ansible-freeipa-v1.7.0/README-vault.md 0000664 0000000 0000000 00000016417 14232747165 0017367 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.8+
**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` | Base64 encoded vault public key. | no
`public_key_file` \| `vault_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-v1.7.0/README.md 0000664 0000000 0000000 00000037246 14232747165 0016241 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
* Modules for automembership rule management
* Modules for automount key management
* Modules for automount location management
* Modules for automount map 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 idrange management
* Modules for location 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.8+ (ansible-freeipa is an Ansible Collection)
* /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**
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
```
Installing collections using the ansible-galaxy command is only supported with ansible 2.9+.
The mazer tool can be used for to install the collection for ansible 2.8:
```bash
mazer 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.
The needed adaptions of collection prefixes for `modules` and `module_utils` will be done with ansible-freeipa release `0.1.6` for galaxy.
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 controller using 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)
Modules in plugin/modules
=========================
* [ipaautomember](README-automember.md)
* [ipaautomountkey](README-automountkey.md)
* [ipaautomountlocation](README-automountlocation.md)
* [ipaautomountmap](README-automountmap.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)
* [idrange](README-idrange.md)
* [ipalocation](README-location.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-v1.7.0/galaxy.yml 0000664 0000000 0000000 00000001102 14232747165 0016750 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-v1.7.0/inventory/ 0000775 0000000 0000000 00000000000 14232747165 0017003 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/inventory/hosts 0000664 0000000 0000000 00000001101 14232747165 0020057 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-v1.7.0/inventory/hosts.cluster 0000664 0000000 0000000 00000001004 14232747165 0021541 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-v1.7.0/inventory/hosts.replica 0000664 0000000 0000000 00000000252 14232747165 0021503 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-v1.7.0/meta/ 0000775 0000000 0000000 00000000000 14232747165 0015674 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/meta/runtime.yml 0000664 0000000 0000000 00000000036 14232747165 0020101 0 ustar 00root root 0000000 0000000 ---
requires_ansible: ">=2.9"
ansible-freeipa-v1.7.0/molecule/ 0000775 0000000 0000000 00000000000 14232747165 0016553 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/c8s-build/ 0000775 0000000 0000000 00000000000 14232747165 0020345 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/c8s-build/Dockerfile 0000664 0000000 0000000 00000001573 14232747165 0022345 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-v1.7.0/molecule/c8s-build/molecule.yml 0000664 0000000 0000000 00000000631 14232747165 0022675 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-v1.7.0/molecule/c8s/ 0000775 0000000 0000000 00000000000 14232747165 0017250 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/c8s/molecule.yml 0000664 0000000 0000000 00000000631 14232747165 0021600 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-v1.7.0/molecule/c9s-build/ 0000775 0000000 0000000 00000000000 14232747165 0020346 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/c9s-build/Dockerfile 0000664 0000000 0000000 00000001535 14232747165 0022344 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-v1.7.0/molecule/c9s-build/molecule.yml 0000664 0000000 0000000 00000000631 14232747165 0022676 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-v1.7.0/molecule/c9s/ 0000775 0000000 0000000 00000000000 14232747165 0017251 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/c9s/molecule.yml 0000664 0000000 0000000 00000000631 14232747165 0021601 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-v1.7.0/molecule/centos-7-build/ 0000775 0000000 0000000 00000000000 14232747165 0021307 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/centos-7-build/molecule.yml 0000664 0000000 0000000 00000000614 14232747165 0023640 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-v1.7.0/molecule/centos-7/ 0000775 0000000 0000000 00000000000 14232747165 0020212 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/centos-7/molecule.yml 0000664 0000000 0000000 00000000643 14232747165 0022545 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-v1.7.0/molecule/centos-8-build/ 0000775 0000000 0000000 00000000000 14232747165 0021310 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/centos-8-build/molecule.yml 0000664 0000000 0000000 00000000616 14232747165 0023643 0 ustar 00root root 0000000 0000000 ---
driver:
name: docker
platforms:
- name: centos-8-build
image: "centos:centos8"
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-v1.7.0/molecule/centos-8/ 0000775 0000000 0000000 00000000000 14232747165 0020213 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/centos-8/molecule.yml 0000664 0000000 0000000 00000000643 14232747165 0022546 0 ustar 00root root 0000000 0000000 ---
driver:
name: docker
platforms:
- name: centos-8
image: quay.io/ansible-freeipa/upstream-tests:centos-8
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-v1.7.0/molecule/default 0000777 0000000 0000000 00000000000 14232747165 0021500 2centos-8 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/fedora-latest-build/ 0000775 0000000 0000000 00000000000 14232747165 0022402 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/fedora-latest-build/Dockerfile 0000664 0000000 0000000 00000001553 14232747165 0024400 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-v1.7.0/molecule/fedora-latest-build/molecule.yml 0000664 0000000 0000000 00000000623 14232747165 0024733 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-v1.7.0/molecule/fedora-latest/ 0000775 0000000 0000000 00000000000 14232747165 0021305 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/fedora-latest/molecule.yml 0000664 0000000 0000000 00000000655 14232747165 0023643 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-v1.7.0/molecule/resources/ 0000775 0000000 0000000 00000000000 14232747165 0020565 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/resources/playbooks/ 0000775 0000000 0000000 00000000000 14232747165 0022570 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/resources/playbooks/library 0000777 0000000 0000000 00000000000 14232747165 0030146 2../../../plugins/modules/ ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/resources/playbooks/module_utils 0000777 0000000 0000000 00000000000 14232747165 0032244 2../../../plugins/module_utils/ ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/molecule/resources/playbooks/prepare-build.yml 0000664 0000000 0000000 00000001224 14232747165 0026045 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-v1.7.0/molecule/resources/playbooks/prepare-common.yml 0000664 0000000 0000000 00000001614 14232747165 0026241 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-v1.7.0/molecule/resources/playbooks/prepare.yml 0000664 0000000 0000000 00000002504 14232747165 0024752 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-v1.7.0/molecule/resources/playbooks/roles 0000777 0000000 0000000 00000000000 14232747165 0025621 2../../../roles/ ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/ 0000775 0000000 0000000 00000000000 14232747165 0016751 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/automember/ 0000775 0000000 0000000 00000000000 14232747165 0021111 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/automember/automember-default-group-not-set.yml 0000664 0000000 0000000 00000000400 14232747165 0030131 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-v1.7.0/playbooks/automember/automember-default-group-set.yml 0000664 0000000 0000000 00000000404 14232747165 0027337 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-v1.7.0/playbooks/automember/automember-default-hostgroup-not-set.yml 0000664 0000000 0000000 00000000414 14232747165 0031034 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-v1.7.0/playbooks/automember/automember-default-hostgroup-set.yml 0000664 0000000 0000000 00000000424 14232747165 0030237 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-v1.7.0/playbooks/automember/automember-group-absent.yml 0000664 0000000 0000000 00000000421 14232747165 0026375 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-v1.7.0/playbooks/automember/automember-group-membership-all-users-rebuilt.yml 0000664 0000000 0000000 00000000432 14232747165 0032627 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-v1.7.0/playbooks/automember/automember-group-membership-users-rebuilt.yml 0000664 0000000 0000000 00000000462 14232747165 0032064 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-v1.7.0/playbooks/automember/automember-group-orphans-removed.yml 0000664 0000000 0000000 00000000421 14232747165 0030232 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-v1.7.0/playbooks/automember/automember-group-present.yml 0000664 0000000 0000000 00000000424 14232747165 0026604 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-v1.7.0/playbooks/automember/automember-hostgroup-absent.yml 0000664 0000000 0000000 00000000445 14232747165 0027301 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-v1.7.0/playbooks/automember/automember-hostgroup-membership-all-hosts-rebuilt.yml 0000664 0000000 0000000 00000000456 14232747165 0033532 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-v1.7.0/playbooks/automember/automember-hostgroup-membership-hosts-rebuilt.yml 0000664 0000000 0000000 00000000524 14232747165 0032760 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-v1.7.0/playbooks/automember/automember-hostgroup-orphans-removed.yml 0000664 0000000 0000000 00000000435 14232747165 0031135 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-v1.7.0/playbooks/automember/automember-hostgroup-present.yml 0000664 0000000 0000000 00000000447 14232747165 0027507 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-v1.7.0/playbooks/automember/automember-hostgroup-rule-absent.yml 0000664 0000000 0000000 00000000624 14232747165 0030245 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-v1.7.0/playbooks/automember/automember-hostgroup-rule-present.yml 0000664 0000000 0000000 00000000627 14232747165 0030454 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-v1.7.0/playbooks/automount/ 0000775 0000000 0000000 00000000000 14232747165 0021004 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/automount/automount-location-absent.yml 0000664 0000000 0000000 00000000441 14232747165 0026641 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-v1.7.0/playbooks/automount/automount-location-present.yml 0000664 0000000 0000000 00000000443 14232747165 0027047 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-v1.7.0/playbooks/automount/automount-map-absent.yaml 0000664 0000000 0000000 00000000377 14232747165 0025757 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-v1.7.0/playbooks/automount/automount-map-present.yaml 0000664 0000000 0000000 00000000416 14232747165 0026155 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-v1.7.0/playbooks/automount/automountkey-present.yml 0000664 0000000 0000000 00000000464 14232747165 0025755 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-v1.7.0/playbooks/automount/automountkey-renamed.yml 0000664 0000000 0000000 00000000536 14232747165 0025710 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-v1.7.0/playbooks/automount/automoutkey-absent.yml 0000664 0000000 0000000 00000000421 14232747165 0025364 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-v1.7.0/playbooks/backup-server-to-controller.yml 0000664 0000000 0000000 00000000331 14232747165 0025043 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-v1.7.0/playbooks/backup-server.yml 0000664 0000000 0000000 00000000175 14232747165 0022250 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to backup IPA server
hosts: ipaserver
become: true
roles:
- role: ipabackup
state: present
ansible-freeipa-v1.7.0/playbooks/config/ 0000775 0000000 0000000 00000000000 14232747165 0020216 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/config/retrieve-config.yml 0000664 0000000 0000000 00000000510 14232747165 0024025 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle global DNS configuration
hosts: ipaserver
become: no
gather_facts: no
tasks:
- name: Query IPA global configuration
ipaconfig:
ipaadmin_password: SomeADMINpassword
register: serverconfig
- name: Display current configuration.
debug:
msg: "{{ serverconfig }}"
ansible-freeipa-v1.7.0/playbooks/config/set-ca-renewal-master-server.yml 0000664 0000000 0000000 00000000414 14232747165 0026344 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle global DNS 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-v1.7.0/playbooks/copy-all-backups-from-server.yml 0000664 0000000 0000000 00000000315 14232747165 0025106 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-v1.7.0/playbooks/copy-backup-from-controller.yml 0000664 0000000 0000000 00000000414 14232747165 0025032 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-v1.7.0/playbooks/copy-backup-from-server.yml 0000664 0000000 0000000 00000000341 14232747165 0024154 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-v1.7.0/playbooks/delegation/ 0000775 0000000 0000000 00000000000 14232747165 0021064 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/delegation/delegation-absent.yml 0000664 0000000 0000000 00000000404 14232747165 0025172 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-v1.7.0/playbooks/delegation/delegation-member-absent.yml 0000664 0000000 0000000 00000000620 14232747165 0026437 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-v1.7.0/playbooks/delegation/delegation-member-present.yml 0000664 0000000 0000000 00000000532 14232747165 0026645 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-v1.7.0/playbooks/delegation/delegation-present.yml 0000664 0000000 0000000 00000000546 14232747165 0025405 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-v1.7.0/playbooks/dnsconfig/ 0000775 0000000 0000000 00000000000 14232747165 0020723 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/dnsconfig/disable-global-forwarders.yml 0000664 0000000 0000000 00000000337 14232747165 0026466 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-v1.7.0/playbooks/dnsconfig/disallow-reverse-sync.yml 0000664 0000000 0000000 00000000366 14232747165 0025714 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-v1.7.0/playbooks/dnsconfig/forwarders-absent.yml 0000664 0000000 0000000 00000000534 14232747165 0025100 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-v1.7.0/playbooks/dnsconfig/forwarders-present.yml 0000664 0000000 0000000 00000000510 14232747165 0025276 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-v1.7.0/playbooks/dnsconfig/set-configuration.yml 0000664 0000000 0000000 00000000535 14232747165 0025111 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-v1.7.0/playbooks/dnsforwardzone/ 0000775 0000000 0000000 00000000000 14232747165 0022016 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/dnsforwardzone/ensure-dnsforwardzone-is-absent.yml 0000664 0000000 0000000 00000000364 14232747165 0030773 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-v1.7.0/playbooks/dnsforwardzone/ensure-dnsforwardzone-is-present.yml 0000664 0000000 0000000 00000000571 14232747165 0031177 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-v1.7.0/playbooks/dnsforwardzone/ensure-dnsforwardzone-with-forwarder-port.yml 0000664 0000000 0000000 00000000564 14232747165 0033036 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-v1.7.0/playbooks/dnsrecord/ 0000775 0000000 0000000 00000000000 14232747165 0020734 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/dnsrecord/ensure-A-and-AAAA-records-are-absent.yml 0000664 0000000 0000000 00000000630 14232747165 0030034 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-v1.7.0/playbooks/dnsrecord/ensure-A-and-AAAA-records-are-present.yml 0000664 0000000 0000000 00000000605 14232747165 0030242 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-v1.7.0/playbooks/dnsrecord/ensure-CNAME-record-is-absent.yml 0000664 0000000 0000000 00000000541 14232747165 0026740 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-v1.7.0/playbooks/dnsrecord/ensure-CNAME-record-is-present.yml 0000664 0000000 0000000 00000000516 14232747165 0027146 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-v1.7.0/playbooks/dnsrecord/ensure-MX-record-is-present.yml 0000664 0000000 0000000 00000000535 14232747165 0026650 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-v1.7.0/playbooks/dnsrecord/ensure-PTR-record-is-present.yml 0000664 0000000 0000000 00000000547 14232747165 0026774 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-v1.7.0/playbooks/dnsrecord/ensure-SRV-record-is-present.yml 0000664 0000000 0000000 00000000565 14232747165 0027001 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-v1.7.0/playbooks/dnsrecord/ensure-SSHFP-record-is-present.yml 0000664 0000000 0000000 00000000703 14232747165 0027204 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-v1.7.0/playbooks/dnsrecord/ensure-TLSA-record-is-present.yml 0000664 0000000 0000000 00000000664 14232747165 0027072 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-v1.7.0/playbooks/dnsrecord/ensure-TXT-record-is-present.yml 0000664 0000000 0000000 00000000527 14232747165 0027004 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-v1.7.0/playbooks/dnsrecord/ensure-URI-record-is-present.yml 0000664 0000000 0000000 00000000617 14232747165 0026764 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-v1.7.0/playbooks/dnsrecord/ensure-dnsrecord-is-absent.yml 0000664 0000000 0000000 00000000535 14232747165 0026627 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-v1.7.0/playbooks/dnsrecord/ensure-dnsrecord-is-present.yml 0000664 0000000 0000000 00000000520 14232747165 0027025 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-v1.7.0/playbooks/dnsrecord/ensure-dnsrecord-with-reverse-is-present.yml 0000664 0000000 0000000 00000000527 14232747165 0031456 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-v1.7.0/playbooks/dnsrecord/ensure-multiple-A-records-are-present.yml 0000664 0000000 0000000 00000000605 14232747165 0030652 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-v1.7.0/playbooks/dnsrecord/ensure-presence-multiple-records.yml 0000664 0000000 0000000 00000001011 14232747165 0030043 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-v1.7.0/playbooks/dnszone/ 0000775 0000000 0000000 00000000000 14232747165 0020431 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/dnszone/disable-zone-forwarders.yml 0000664 0000000 0000000 00000000364 14232747165 0025707 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-v1.7.0/playbooks/dnszone/dnszone-absent.yml 0000664 0000000 0000000 00000000337 14232747165 0024111 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-v1.7.0/playbooks/dnszone/dnszone-all-params.yml 0000664 0000000 0000000 00000001475 14232747165 0024672 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
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-v1.7.0/playbooks/dnszone/dnszone-disable.yml 0000664 0000000 0000000 00000000331 14232747165 0024232 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-v1.7.0/playbooks/dnszone/dnszone-enable.yml 0000664 0000000 0000000 00000000326 14232747165 0024061 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-v1.7.0/playbooks/dnszone/dnszone-present.yml 0000664 0000000 0000000 00000000325 14232747165 0024312 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-v1.7.0/playbooks/dnszone/dnszone-reverse-from-ip.yml 0000664 0000000 0000000 00000000574 14232747165 0025662 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`
debug:
msg: "Zone created: {{ result.dnszone.name }}"
ansible-freeipa-v1.7.0/playbooks/hbacrule/ 0000775 0000000 0000000 00000000000 14232747165 0020536 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/hbacrule/ensure-hbarule-allhosts-absent.yml 0000664 0000000 0000000 00000000347 14232747165 0027307 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-v1.7.0/playbooks/hbacrule/ensure-hbarule-allhosts-disabled.yml 0000664 0000000 0000000 00000000353 14232747165 0027577 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-v1.7.0/playbooks/hbacrule/ensure-hbarule-allhosts-enabled.yml 0000664 0000000 0000000 00000000351 14232747165 0027420 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-v1.7.0/playbooks/hbacrule/ensure-hbarule-allhosts-present.yml 0000664 0000000 0000000 00000000354 14232747165 0027511 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-v1.7.0/playbooks/hbacrule/ensure-hbarule-allhosts-server-member-absent.yml 0000664 0000000 0000000 00000000436 14232747165 0032057 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-v1.7.0/playbooks/hbacrule/ensure-hbarule-allhosts-server-member-present.yml 0000664 0000000 0000000 00000000413 14232747165 0032256 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-v1.7.0/playbooks/hbacsvc/ 0000775 0000000 0000000 00000000000 14232747165 0020362 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/hbacsvc/ensure-hbacsvc-absent.yml 0000664 0000000 0000000 00000000365 14232747165 0025273 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-v1.7.0/playbooks/hbacsvc/ensure-hbacsvc-present.yml 0000664 0000000 0000000 00000000620 14232747165 0025471 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-v1.7.0/playbooks/hbacsvcgroup/ 0000775 0000000 0000000 00000000000 14232747165 0021437 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/hbacsvcgroup/ensure-hbacsvcgroup-absent.yml 0000664 0000000 0000000 00000000412 14232747165 0027416 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-v1.7.0/playbooks/hbacsvcgroup/ensure-hbacsvcgroup-member-absent.yml 0000664 0000000 0000000 00000000465 14232747165 0030673 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-v1.7.0/playbooks/hbacsvcgroup/ensure-hbacsvcgroup-member-present.yml 0000664 0000000 0000000 00000000441 14232747165 0031071 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-v1.7.0/playbooks/hbacsvcgroup/ensure-hbacsvcgroup-present.yml 0000664 0000000 0000000 00000000441 14232747165 0027624 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-v1.7.0/playbooks/host/ 0000775 0000000 0000000 00000000000 14232747165 0017726 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/host/add-host.yml 0000777 0000000 0000000 00000000000 14232747165 0025325 2host-present.yml ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/host/delete-host.yml 0000664 0000000 0000000 00000000357 14232747165 0022673 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-v1.7.0/playbooks/host/disable-host.yml 0000664 0000000 0000000 00000000350 14232747165 0023025 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-v1.7.0/playbooks/host/ensure_host_with_randompassword.yml 0000664 0000000 0000000 00000000710 14232747165 0027163 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
debug:
var: ipahost.host.randompassword
ansible-freeipa-v1.7.0/playbooks/host/host-member-allow_create_keytab-absent.yml 0000664 0000000 0000000 00000001155 14232747165 0030145 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-v1.7.0/playbooks/host/host-member-allow_create_keytab-present.yml 0000664 0000000 0000000 00000001133 14232747165 0030345 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-v1.7.0/playbooks/host/host-member-allow_retrieve_keytab-absent.yml 0000664 0000000 0000000 00000001171 14232747165 0030525 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-v1.7.0/playbooks/host/host-member-allow_retrieve_keytab-present.yml 0000664 0000000 0000000 00000001147 14232747165 0030734 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-v1.7.0/playbooks/host/host-member-certificate-absent.yml 0000664 0000000 0000000 00000002726 14232747165 0026434 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-v1.7.0/playbooks/host/host-member-certificate-present.yml 0000664 0000000 0000000 00000002704 14232747165 0026634 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-v1.7.0/playbooks/host/host-member-ipaddresses-absent.yml 0000664 0000000 0000000 00000000620 14232747165 0026447 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-v1.7.0/playbooks/host/host-member-ipaddresses-present.yml 0000664 0000000 0000000 00000000576 14232747165 0026665 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-v1.7.0/playbooks/host/host-member-managedby_host-absent.yml 0000664 0000000 0000000 00000000516 14232747165 0027131 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-v1.7.0/playbooks/host/host-member-managedby_host-present.yml 0000664 0000000 0000000 00000000474 14232747165 0027340 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-v1.7.0/playbooks/host/host-member-principal-absent.yml 0000664 0000000 0000000 00000000632 14232747165 0026125 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-v1.7.0/playbooks/host/host-member-principal-present.yml 0000664 0000000 0000000 00000000610 14232747165 0026325 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-v1.7.0/playbooks/host/host-present-with-allow_create_keytab.yml 0000664 0000000 0000000 00000001141 14232747165 0030050 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-v1.7.0/playbooks/host/host-present-with-allow_retrieve_keytab.yml 0000664 0000000 0000000 00000001155 14232747165 0030437 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-v1.7.0/playbooks/host/host-present-with-certificate.yml 0000664 0000000 0000000 00000002674 14232747165 0026346 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-v1.7.0/playbooks/host/host-present-with-managedby_host.yml 0000664 0000000 0000000 00000000452 14232747165 0027040 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-v1.7.0/playbooks/host/host-present-with-principal.yml 0000664 0000000 0000000 00000000607 14232747165 0026037 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-v1.7.0/playbooks/host/host-present-with-randompassword.yml 0000664 0000000 0000000 00000000606 14232747165 0027120 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
debug:
var: ipahost.host.randompassword
ansible-freeipa-v1.7.0/playbooks/host/host-present-with-several-ip-addresses.yml 0000664 0000000 0000000 00000001114 14232747165 0030072 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-v1.7.0/playbooks/host/host-present.yml 0000664 0000000 0000000 00000000722 14232747165 0023105 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-v1.7.0/playbooks/host/hosts-member-certificate-absent.yml 0000664 0000000 0000000 00000005462 14232747165 0026617 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-v1.7.0/playbooks/host/hosts-member-certificate-present.yml 0000664 0000000 0000000 00000005440 14232747165 0027017 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-v1.7.0/playbooks/host/hosts-member-managedby_host-absent.yml 0000664 0000000 0000000 00000000622 14232747165 0027312 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-v1.7.0/playbooks/host/hosts-member-managedby_host-present.yml 0000664 0000000 0000000 00000000600 14232747165 0027512 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-v1.7.0/playbooks/host/hosts-member-principal-absent.yml 0000664 0000000 0000000 00000000746 14232747165 0026316 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-v1.7.0/playbooks/host/hosts-member-principal-present.yml 0000664 0000000 0000000 00000000725 14232747165 0026517 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-v1.7.0/playbooks/host/hosts-present-with-certificate.yml 0000664 0000000 0000000 00000005430 14232747165 0026522 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-v1.7.0/playbooks/host/hosts-present-with-managedby_host.yml 0000664 0000000 0000000 00000000636 14232747165 0027227 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-v1.7.0/playbooks/host/hosts-present-with-randompasswords.yml 0000664 0000000 0000000 00000001263 14232747165 0027466 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
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
ansible-freeipa-v1.7.0/playbooks/hostgroup/ 0000775 0000000 0000000 00000000000 14232747165 0021003 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/hostgroup/ensure-hostgroup-is-absent.yml 0000664 0000000 0000000 00000000355 14232747165 0026745 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-v1.7.0/playbooks/hostgroup/ensure-hostgroup-is-present.yml 0000664 0000000 0000000 00000000471 14232747165 0027150 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-v1.7.0/playbooks/hostgroup/ensure-hosts-and-hostgroups-are-absent-in-hostgroup.yml 0000664 0000000 0000000 00000000602 14232747165 0033611 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-v1.7.0/playbooks/hostgroup/ensure-hosts-and-hostgroups-are-present-in-hostgroup.yml 0000664 0000000 0000000 00000000557 14232747165 0034026 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-v1.7.0/playbooks/hostgroup/rename-hostgroup.yml 0000664 0000000 0000000 00000000417 14232747165 0025027 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-v1.7.0/playbooks/idrange/ 0000775 0000000 0000000 00000000000 14232747165 0020362 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/idrange/idrange-absent.yml 0000664 0000000 0000000 00000000324 14232747165 0023767 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-v1.7.0/playbooks/idrange/idrange-ad-posix-present.yml 0000664 0000000 0000000 00000000523 14232747165 0025716 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-v1.7.0/playbooks/idrange/idrange-ad-present.yml 0000664 0000000 0000000 00000000627 14232747165 0024563 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-v1.7.0/playbooks/idrange/idrange-present.yml 0000664 0000000 0000000 00000000471 14232747165 0024176 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-v1.7.0/playbooks/install-client.yml 0000664 0000000 0000000 00000000231 14232747165 0022412 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-v1.7.0/playbooks/install-cluster.yml 0000664 0000000 0000000 00000000530 14232747165 0022617 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-v1.7.0/playbooks/install-replica.yml 0000664 0000000 0000000 00000000205 14232747165 0022554 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to configure IPA replicas
hosts: ipareplicas
become: true
roles:
- role: ipareplica
state: present
ansible-freeipa-v1.7.0/playbooks/install-server.yml 0000664 0000000 0000000 00000000201 14232747165 0022437 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to configure IPA servers
hosts: ipaserver
become: true
roles:
- role: ipaserver
state: present
ansible-freeipa-v1.7.0/playbooks/location/ 0000775 0000000 0000000 00000000000 14232747165 0020561 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/location/location-absent.yml 0000664 0000000 0000000 00000000347 14232747165 0024372 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-v1.7.0/playbooks/location/location-present.yml 0000664 0000000 0000000 00000000325 14232747165 0024572 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-v1.7.0/playbooks/permission/ 0000775 0000000 0000000 00000000000 14232747165 0021141 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/permission/permission-absent.yml 0000664 0000000 0000000 00000000340 14232747165 0025323 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-v1.7.0/playbooks/permission/permission-allow-read-employeenum.yml 0000664 0000000 0000000 00000000603 14232747165 0030435 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-v1.7.0/playbooks/permission/permission-member-absent.yml 0000664 0000000 0000000 00000000476 14232747165 0026602 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-v1.7.0/playbooks/permission/permission-member-present.yml 0000664 0000000 0000000 00000000466 14232747165 0027005 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-v1.7.0/playbooks/permission/permission-present.yml 0000664 0000000 0000000 00000000367 14232747165 0025540 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-v1.7.0/playbooks/permission/permission-renamed.yml 0000664 0000000 0000000 00000000436 14232747165 0025470 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-v1.7.0/playbooks/privilege/ 0000775 0000000 0000000 00000000000 14232747165 0020737 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/privilege/privilege-absent.yml 0000664 0000000 0000000 00000000365 14232747165 0024726 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-v1.7.0/playbooks/privilege/privilege-member-absent.yml 0000664 0000000 0000000 00000000521 14232747165 0026165 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-v1.7.0/playbooks/privilege/privilege-member-present.yml 0000664 0000000 0000000 00000000627 14232747165 0026400 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-v1.7.0/playbooks/privilege/privilege-present.yml 0000664 0000000 0000000 00000000404 14232747165 0025124 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-v1.7.0/playbooks/pwpolicy/ 0000775 0000000 0000000 00000000000 14232747165 0020617 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/pwpolicy/pwpolicy_absent.yml 0000664 0000000 0000000 00000000351 14232747165 0024543 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-v1.7.0/playbooks/pwpolicy/pwpolicy_present.yml 0000664 0000000 0000000 00000000601 14232747165 0024745 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-v1.7.0/playbooks/remove-all-backups-from-server.yml 0000664 0000000 0000000 00000000256 14232747165 0025435 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-v1.7.0/playbooks/remove-backup-from-server.yml 0000664 0000000 0000000 00000000302 14232747165 0024474 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-v1.7.0/playbooks/restore-server-from-controller.yml 0000664 0000000 0000000 00000000450 14232747165 0025604 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-v1.7.0/playbooks/restore-server.yml 0000664 0000000 0000000 00000000343 14232747165 0022463 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-v1.7.0/playbooks/role/ 0000775 0000000 0000000 00000000000 14232747165 0017712 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/role/role-is-absent.yml 0000664 0000000 0000000 00000000351 14232747165 0023260 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-v1.7.0/playbooks/role/role-is-present.yml 0000664 0000000 0000000 00000000370 14232747165 0023465 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-v1.7.0/playbooks/role/role-member-group-absent.yml 0000664 0000000 0000000 00000000461 14232747165 0025250 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-v1.7.0/playbooks/role/role-member-group-present.yml 0000664 0000000 0000000 00000000436 14232747165 0025456 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-v1.7.0/playbooks/role/role-member-host-absent.yml 0000664 0000000 0000000 00000000472 14232747165 0025073 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-v1.7.0/playbooks/role/role-member-host-present.yml 0000664 0000000 0000000 00000000447 14232747165 0025301 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-v1.7.0/playbooks/role/role-member-hostgroup-absent.yml 0000664 0000000 0000000 00000000475 14232747165 0026153 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-v1.7.0/playbooks/role/role-member-hostgroup-present.yml 0000664 0000000 0000000 00000000452 14232747165 0026352 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-v1.7.0/playbooks/role/role-member-privilege-absent.yml 0000664 0000000 0000000 00000000542 14232747165 0026102 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-v1.7.0/playbooks/role/role-member-privilege-present.yml 0000664 0000000 0000000 00000000517 14232747165 0026310 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-v1.7.0/playbooks/role/role-member-service-absent.yml 0000664 0000000 0000000 00000000502 14232747165 0025550 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-v1.7.0/playbooks/role/role-member-service-present.yml 0000664 0000000 0000000 00000000444 14232747165 0025761 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-v1.7.0/playbooks/role/role-member-user-absent.yml 0000664 0000000 0000000 00000000455 14232747165 0025075 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-v1.7.0/playbooks/role/role-member-user-present.yml 0000664 0000000 0000000 00000000432 14232747165 0025274 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-v1.7.0/playbooks/role/role-members-absent.yml 0000664 0000000 0000000 00000000774 14232747165 0024310 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-v1.7.0/playbooks/role/role-members-present.yml 0000664 0000000 0000000 00000000757 14232747165 0024515 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-v1.7.0/playbooks/role/role-rename.yml 0000664 0000000 0000000 00000000345 14232747165 0022645 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-v1.7.0/playbooks/selfservice/ 0000775 0000000 0000000 00000000000 14232747165 0021263 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/selfservice/selfservice-absent.yml 0000664 0000000 0000000 00000000407 14232747165 0025573 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-v1.7.0/playbooks/selfservice/selfservice-member-absent.yml 0000664 0000000 0000000 00000000637 14232747165 0027045 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-v1.7.0/playbooks/selfservice/selfservice-member-present.yml 0000664 0000000 0000000 00000000535 14232747165 0027246 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-v1.7.0/playbooks/selfservice/selfservice-present.yml 0000664 0000000 0000000 00000000466 14232747165 0026004 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-v1.7.0/playbooks/server/ 0000775 0000000 0000000 00000000000 14232747165 0020257 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/server/server-absent-continue.yml 0000664 0000000 0000000 00000000446 14232747165 0025410 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-v1.7.0/playbooks/server/server-absent-force.yml 0000664 0000000 0000000 00000000431 14232747165 0024654 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-v1.7.0/playbooks/server/server-absent-ignore_last_of_role.yml 0000664 0000000 0000000 00000000477 14232747165 0027603 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-v1.7.0/playbooks/server/server-absent-ignore_topology_disconnect.yml 0000664 0000000 0000000 00000000536 14232747165 0031214 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-v1.7.0/playbooks/server/server-absent.yml 0000664 0000000 0000000 00000000362 14232747165 0023563 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-v1.7.0/playbooks/server/server-hidden.yml 0000664 0000000 0000000 00000000373 14232747165 0023544 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-v1.7.0/playbooks/server/server-location.yml 0000664 0000000 0000000 00000000471 14232747165 0024120 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-v1.7.0/playbooks/server/server-no-location.yml 0000664 0000000 0000000 00000000407 14232747165 0024531 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-v1.7.0/playbooks/server/server-no-service-weight.yml 0000664 0000000 0000000 00000000426 14232747165 0025647 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-v1.7.0/playbooks/server/server-not-hidden.yml 0000664 0000000 0000000 00000000401 14232747165 0024332 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-v1.7.0/playbooks/server/server-present.yml 0000664 0000000 0000000 00000000351 14232747165 0023765 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-v1.7.0/playbooks/server/server-service-weight.yml 0000664 0000000 0000000 00000000424 14232747165 0025233 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-v1.7.0/playbooks/service/ 0000775 0000000 0000000 00000000000 14232747165 0020411 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/service/service-host-is-absent.yml 0000664 0000000 0000000 00000000507 14232747165 0025434 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-v1.7.0/playbooks/service/service-host-is-present.yml 0000664 0000000 0000000 00000000464 14232747165 0025642 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-v1.7.0/playbooks/service/service-is-absent.yml 0000664 0000000 0000000 00000000401 14232747165 0024452 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-v1.7.0/playbooks/service/service-is-disabled.yml 0000664 0000000 0000000 00000000406 14232747165 0024752 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-v1.7.0/playbooks/service/service-is-present-with-all-attributes.yml 0000664 0000000 0000000 00000002451 14232747165 0030570 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-v1.7.0/playbooks/service/service-is-present-with-host-force.yml 0000664 0000000 0000000 00000000377 14232747165 0027712 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-v1.7.0/playbooks/service/service-is-present-without-host-object.yml 0000664 0000000 0000000 00000000411 14232747165 0030577 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-v1.7.0/playbooks/service/service-is-present.yml 0000664 0000000 0000000 00000000356 14232747165 0024667 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-v1.7.0/playbooks/service/service-member-allow_create_keytab-absent.yml 0000664 0000000 0000000 00000001173 14232747165 0031313 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-v1.7.0/playbooks/service/service-member-allow_create_keytab-present.yml 0000664 0000000 0000000 00000001151 14232747165 0031513 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-v1.7.0/playbooks/service/service-member-allow_retrieve_keytab-absent.yml 0000664 0000000 0000000 00000001207 14232747165 0031673 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-v1.7.0/playbooks/service/service-member-allow_retrieve_keytab-present.yml 0000664 0000000 0000000 00000001165 14232747165 0032102 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-v1.7.0/playbooks/service/service-member-certificate-absent.yml 0000664 0000000 0000000 00000002204 14232747165 0027571 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-v1.7.0/playbooks/service/service-member-certificate-present.yml 0000664 0000000 0000000 00000002207 14232747165 0030000 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-v1.7.0/playbooks/service/service-member-principal-absent.yml 0000664 0000000 0000000 00000000544 14232747165 0027275 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-v1.7.0/playbooks/service/service-member-principal-present.yml 0000664 0000000 0000000 00000000522 14232747165 0027475 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-v1.7.0/playbooks/servicedelegationrule/ 0000775 0000000 0000000 00000000000 14232747165 0023335 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/servicedelegationrule/servicedelegationrule-absent.yml 0000664 0000000 0000000 00000000437 14232747165 0031722 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-v1.7.0/playbooks/servicedelegationrule/servicedelegationrule-present.yml 0000664 0000000 0000000 00000000415 14232747165 0032122 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 14232747165 0035064 0 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/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 14232747165 0035273 0 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/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 14232747165 0034372 0 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/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 14232747165 0034601 0 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/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-v1.7.0/playbooks/servicedelegationtarget/ 0000775 0000000 0000000 00000000000 14232747165 0023654 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/servicedelegationtarget/servicedelegationtarget-absent.yml 0000664 0000000 0000000 00000000451 14232747165 0032554 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-v1.7.0/playbooks/servicedelegationtarget/servicedelegationtarget-member-absent.yml 0000664 0000000 0000000 00000000573 14232747165 0034026 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-v1.7.0/playbooks/servicedelegationtarget/servicedelegationtarget-member-present.yml 0000664 0000000 0000000 00000000560 14232747165 0034226 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-v1.7.0/playbooks/servicedelegationtarget/servicedelegationtarget-present.yml 0000664 0000000 0000000 00000000427 14232747165 0032763 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-v1.7.0/playbooks/sudocmd/ 0000775 0000000 0000000 00000000000 14232747165 0020407 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/sudocmd/ensure-sudocmd-is-absent.yml 0000664 0000000 0000000 00000000347 14232747165 0025756 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-v1.7.0/playbooks/sudocmd/ensure-sudocmd-is-present.yml 0000664 0000000 0000000 00000000351 14232747165 0026155 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-v1.7.0/playbooks/sudocmdgroup/ 0000775 0000000 0000000 00000000000 14232747165 0021464 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/sudocmdgroup/ensure-sudocmd-are-absent-in-sudocmdgroup.yml 0000664 0000000 0000000 00000000516 14232747165 0032302 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-v1.7.0/playbooks/sudocmdgroup/ensure-sudocmd-are-present-in-sudocmdgroup.yml 0000664 0000000 0000000 00000000770 14232747165 0032510 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-v1.7.0/playbooks/sudocmdgroup/ensure-sudocmdgroup-is-absent.yml 0000664 0000000 0000000 00000000404 14232747165 0030102 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-v1.7.0/playbooks/sudocmdgroup/ensure-sudocmdgroup-is-present.yml 0000664 0000000 0000000 00000000550 14232747165 0030310 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-v1.7.0/playbooks/sudorule/ 0000775 0000000 0000000 00000000000 14232747165 0020613 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/sudorule/ensure-sudorule-does-not-have-sudooption.yml 0000664 0000000 0000000 00000000443 14232747165 0031350 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-v1.7.0/playbooks/sudorule/ensure-sudorule-has-sudooption.yml 0000664 0000000 0000000 00000000420 14232747165 0027445 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-v1.7.0/playbooks/sudorule/ensure-sudorule-host-member-is-absent.yml 0000664 0000000 0000000 00000000427 14232747165 0030605 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-v1.7.0/playbooks/sudorule/ensure-sudorule-host-member-is-present.yml 0000664 0000000 0000000 00000000404 14232747165 0031004 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-v1.7.0/playbooks/sudorule/ensure-sudorule-hostgroup-member-is-absent.yml 0000664 0000000 0000000 00000000443 14232747165 0031660 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-v1.7.0/playbooks/sudorule/ensure-sudorule-hostgroup-member-is-present.yml 0000664 0000000 0000000 00000000420 14232747165 0032057 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-v1.7.0/playbooks/sudorule/ensure-sudorule-is-absent.yml 0000664 0000000 0000000 00000000320 14232747165 0026355 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-v1.7.0/playbooks/sudorule/ensure-sudorule-is-disabled.yml 0000664 0000000 0000000 00000000324 14232747165 0026654 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-v1.7.0/playbooks/sudorule/ensure-sudorule-is-enabled.yml 0000664 0000000 0000000 00000000322 14232747165 0026475 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-v1.7.0/playbooks/sudorule/ensure-sudorule-is-present-with-order.yml 0000664 0000000 0000000 00000000360 14232747165 0030647 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-v1.7.0/playbooks/sudorule/ensure-sudorule-is-present.yml 0000664 0000000 0000000 00000000461 14232747165 0026567 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-v1.7.0/playbooks/sudorule/ensure-sudorule-runasuser-is-absent.yml 0000664 0000000 0000000 00000000446 14232747165 0030413 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-v1.7.0/playbooks/sudorule/ensure-sudorule-runasuser-is-present.yml 0000664 0000000 0000000 00000000423 14232747165 0030612 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-v1.7.0/playbooks/sudorule/ensure-sudorule-sudocmd-is-absent.yml 0000664 0000000 0000000 00000000642 14232747165 0030020 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-v1.7.0/playbooks/sudorule/ensure-sudorule-sudocmd-is-present.yml 0000664 0000000 0000000 00000000617 14232747165 0030226 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-v1.7.0/playbooks/topology/ 0000775 0000000 0000000 00000000000 14232747165 0020625 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/topology/add-topologysegment.yml 0000664 0000000 0000000 00000000456 14232747165 0025342 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-v1.7.0/playbooks/topology/add-topologysegments.yml 0000664 0000000 0000000 00000001374 14232747165 0025525 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-v1.7.0/playbooks/topology/check-topologysegments.yml 0000664 0000000 0000000 00000001374 14232747165 0026052 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-v1.7.0/playbooks/topology/delete-topologysegment.yml 0000664 0000000 0000000 00000000460 14232747165 0026047 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-v1.7.0/playbooks/topology/delete-topologysegments.yml 0000664 0000000 0000000 00000001373 14232747165 0026236 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-v1.7.0/playbooks/topology/reinitialize-topologysegment.yml 0000664 0000000 0000000 00000000534 14232747165 0027277 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-v1.7.0/playbooks/topology/verify-topologysuffix.yml 0000664 0000000 0000000 00000000350 14232747165 0025751 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-v1.7.0/playbooks/trust/ 0000775 0000000 0000000 00000000000 14232747165 0020132 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/trust/add-trust.yml 0000664 0000000 0000000 00000000453 14232747165 0022566 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-v1.7.0/playbooks/trust/del-trust.yml 0000664 0000000 0000000 00000000350 14232747165 0022576 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-v1.7.0/playbooks/uninstall-client.yml 0000664 0000000 0000000 00000000203 14232747165 0022754 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to unconfigure IPA clients
hosts: ipaclients
become: true
roles:
- role: ipaclient
state: absent
ansible-freeipa-v1.7.0/playbooks/uninstall-cluster.yml 0000664 0000000 0000000 00000000533 14232747165 0023165 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-v1.7.0/playbooks/uninstall-replica.yml 0000664 0000000 0000000 00000000206 14232747165 0023120 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to unconfigure IPA replicas
hosts: ipareplicas
become: true
roles:
- role: ipareplica
state: absent
ansible-freeipa-v1.7.0/playbooks/uninstall-server.yml 0000664 0000000 0000000 00000000202 14232747165 0023003 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to unconfigure IPA servers
hosts: ipaserver
become: true
roles:
- role: ipaserver
state: absent
ansible-freeipa-v1.7.0/playbooks/user/ 0000775 0000000 0000000 00000000000 14232747165 0017727 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/user/add-group.yml 0000664 0000000 0000000 00000000712 14232747165 0022334 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-v1.7.0/playbooks/user/add-groups-to-group.yml 0000664 0000000 0000000 00000000404 14232747165 0024267 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-v1.7.0/playbooks/user/add-user-to-group.yml 0000664 0000000 0000000 00000000375 14232747165 0023735 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-v1.7.0/playbooks/user/add-user.yml 0000664 0000000 0000000 00000000635 14232747165 0022162 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-v1.7.0/playbooks/user/delete-group.yml 0000664 0000000 0000000 00000000353 14232747165 0023047 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-v1.7.0/playbooks/user/delete-preserve-user.yml 0000664 0000000 0000000 00000000354 14232747165 0024523 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-v1.7.0/playbooks/user/delete-user.yml 0000664 0000000 0000000 00000000313 14232747165 0022665 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-v1.7.0/playbooks/user/disable-user.yml 0000664 0000000 0000000 00000000316 14232747165 0023031 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-v1.7.0/playbooks/user/enable-user.yml 0000664 0000000 0000000 00000000314 14232747165 0022652 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-v1.7.0/playbooks/user/ensure_user_with_randompassword.yml 0000664 0000000 0000000 00000000641 14232747165 0027170 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
debug:
var: ipauser.user.randompassword
ansible-freeipa-v1.7.0/playbooks/user/ensure_users_with_randompasswords.yml 0000664 0000000 0000000 00000001165 14232747165 0027540 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
debug:
var: ipauser.user.user1.randompassword
- name: Print generated random password for user2
debug:
var: ipauser.user.user2.randompassword
ansible-freeipa-v1.7.0/playbooks/user/undelete-user.yml 0000664 0000000 0000000 00000000332 14232747165 0023231 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-v1.7.0/playbooks/user/unlock-users.yml 0000664 0000000 0000000 00000000336 14232747165 0023106 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-v1.7.0/playbooks/user/user_certificate_absent.yml 0000664 0000000 0000000 00000007655 14232747165 0025343 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-v1.7.0/playbooks/user/user_certificate_present.yml 0000664 0000000 0000000 00000007632 14232747165 0025542 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-v1.7.0/playbooks/user/user_present.yml 0000664 0000000 0000000 00000002011 14232747165 0023162 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-v1.7.0/playbooks/user/users_absent.yml 0000664 0000000 0000000 00000001454 14232747165 0023153 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-v1.7.0/playbooks/user/users_certificate_absent.yml 0000664 0000000 0000000 00000007651 14232747165 0025522 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-v1.7.0/playbooks/user/users_certificate_present.yml 0000664 0000000 0000000 00000007626 14232747165 0025730 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-v1.7.0/playbooks/user/users_present.yml 0000664 0000000 0000000 00000001425 14232747165 0023355 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-v1.7.0/playbooks/vault/ 0000775 0000000 0000000 00000000000 14232747165 0020104 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/playbooks/vault/change-password-symmetric-vault.yml 0000664 0000000 0000000 00000000667 14232747165 0027070 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-v1.7.0/playbooks/vault/data-archive-in-asymmetric-vault.yml 0000664 0000000 0000000 00000000460 14232747165 0027067 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-v1.7.0/playbooks/vault/data-archive-in-symmetric-vault.yml 0000664 0000000 0000000 00000000526 14232747165 0026731 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-v1.7.0/playbooks/vault/ensure-asymetric-vault-is-absent.yml 0000664 0000000 0000000 00000000372 14232747165 0027144 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-v1.7.0/playbooks/vault/ensure-asymetric-vault-is-present.yml 0000664 0000000 0000000 00000001311 14232747165 0027342 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-v1.7.0/playbooks/vault/ensure-service-vault-is-absent.yml 0000664 0000000 0000000 00000000420 14232747165 0026576 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-v1.7.0/playbooks/vault/ensure-service-vault-is-present.yml 0000664 0000000 0000000 00000000475 14232747165 0027014 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-v1.7.0/playbooks/vault/ensure-shared-vault-is-absent.yml 0000664 0000000 0000000 00000000365 14232747165 0026414 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-v1.7.0/playbooks/vault/ensure-shared-vault-is-present.yml 0000664 0000000 0000000 00000000442 14232747165 0026614 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-v1.7.0/playbooks/vault/ensure-standard-vault-is-absent.yml 0000664 0000000 0000000 00000000356 14232747165 0026746 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-v1.7.0/playbooks/vault/ensure-standard-vault-is-present.yml 0000664 0000000 0000000 00000000454 14232747165 0027151 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-v1.7.0/playbooks/vault/ensure-symetric-vault-is-absent.yml 0000664 0000000 0000000 00000000370 14232747165 0027001 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-v1.7.0/playbooks/vault/ensure-symetric-vault-is-present.yml 0000664 0000000 0000000 00000000415 14232747165 0027205 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-v1.7.0/playbooks/vault/ensure-vault-is-present-with-members.yml 0000664 0000000 0000000 00000000516 14232747165 0027753 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-v1.7.0/playbooks/vault/ensure-vault-member-group-is-absent.yml 0000664 0000000 0000000 00000000451 14232747165 0027543 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-v1.7.0/playbooks/vault/ensure-vault-member-group-is-present.yml 0000664 0000000 0000000 00000000453 14232747165 0027751 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-v1.7.0/playbooks/vault/ensure-vault-member-user-is-absent.yml 0000664 0000000 0000000 00000000474 14232747165 0027372 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-v1.7.0/playbooks/vault/ensure-vault-member-user-is-present.yml 0000664 0000000 0000000 00000000446 14232747165 0027575 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-v1.7.0/playbooks/vault/ensure-vault-owner-is-absent.yml 0000664 0000000 0000000 00000000514 14232747165 0026274 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-v1.7.0/playbooks/vault/ensure-vault-owner-is-present.yml 0000664 0000000 0000000 00000000516 14232747165 0026502 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-v1.7.0/playbooks/vault/password.txt 0000664 0000000 0000000 00000000022 14232747165 0022501 0 ustar 00root root 0000000 0000000 SomeVAULTpassword
ansible-freeipa-v1.7.0/playbooks/vault/private.pem 0000664 0000000 0000000 00000003213 14232747165 0022260 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-v1.7.0/playbooks/vault/public.pem 0000664 0000000 0000000 00000000703 14232747165 0022065 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-v1.7.0/playbooks/vault/retrive-data-asymmetric-vault.yml 0000664 0000000 0000000 00000000715 14232747165 0026525 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.
debug:
msg: "Data: {{ result.vault.data }}"
ansible-freeipa-v1.7.0/playbooks/vault/retrive-data-symmetric-vault.yml 0000664 0000000 0000000 00000000660 14232747165 0026363 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.
debug:
msg: "Data: {{ result.vault.data }}"
ansible-freeipa-v1.7.0/playbooks/vault/vault-is-present-with-password-file.yml 0000664 0000000 0000000 00000001350 14232747165 0027576 0 ustar 00root root 0000000 0000000 ---
- name: Tests
hosts: ipaserver
become: true
gather_facts: True
tasks:
- name: Copy file containing password to server.
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.
file:
path: "{{ ansible_facts['env'].HOME }}/password.txt"
state: absent
ansible-freeipa-v1.7.0/playbooks/vault/vault-is-present-with-public-key-file.yml 0000664 0000000 0000000 00000001600 14232747165 0027776 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.
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.
file:
path: "{{ ansible_facts['env'].HOME }}/public.pem"
state: absent
ansible-freeipa-v1.7.0/plugins/ 0000775 0000000 0000000 00000000000 14232747165 0016427 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/plugins/doc_fragments/ 0000775 0000000 0000000 00000000000 14232747165 0021242 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/plugins/doc_fragments/ipamodule_base_docs.py 0000664 0000000 0000000 00000003322 14232747165 0025575 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
ipaadmin_password:
description: The admin password.
required: false
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"]
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-v1.7.0/plugins/module_utils/ 0000775 0000000 0000000 00000000000 14232747165 0021134 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/plugins/module_utils/ansible_freeipa_module.py 0000664 0000000 0000000 00000147033 14232747165 0026173 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Sergio Oliveira Campos
# Thomas Woerner
#
# Copyright (C) 2019 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", "get_credentials_if_valid", "Encoding",
"load_pem_x509_certificate", "DNSName"]
import sys
# HACK: workaround for Ansible 2.9
# https://github.com/ansible/ansible/issues/68361
if 'ansible.executor' in sys.modules:
for attr in __all__:
setattr(sys.modules[__name__], attr, None)
else:
import operator
import os
import uuid
import tempfile
import shutil
import netaddr
import gssapi
from datetime import datetime
from contextlib import contextmanager
import inspect
# ansible-freeipa requires locale to be C, IPA requires utf-8.
os.environ["LANGUAGE"] = "C"
try:
from packaging import version
except ImportError:
# If `packaging` not found, split version string for creating version
# object. Although it is not PEP 440 compliant, it will work for stable
# FreeIPA releases.
import re
class version: # pylint: disable=invalid-name, too-few-public-methods
@staticmethod
def parse(version_str):
"""
Split a version string A.B.C, into a tuple.
This will not work for `rc`, `dev` or similar version string.
"""
return tuple(re.split("[-_.]", version_str)) # noqa: W605
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.dn import DN
from ipapython.version import VERSION
from ipaplatform.paths import paths
from ipalib.krb_utils import get_credentials_if_valid
from ipapython.dnsutil import DNSName
from ipapython import kerberos
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils.common.text.converters import jsonify
try:
from ipalib.x509 import Encoding
except ImportError:
from cryptography.hazmat.primitives.serialization import Encoding
try:
from ipalib.x509 import load_pem_x509_certificate
except ImportError:
from ipalib.x509 import load_certificate
load_pem_x509_certificate = None
import socket
import base64
from ansible.module_utils import six
try:
from collections.abc import Mapping # noqa
except ImportError:
from collections import Mapping # pylint: disable=deprecated-class
# 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()
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: {}".format(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)
del os.environ['KRB5CCNAME']
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)
"""
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
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(version.parse(VERSION),
version.parse(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_string=False):
value = _afm_convert(module.params.get(name))
# Fail on empty strings in the list or if allow_empty_string 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_string:
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_string=False):
value = module_params_get(module, name, allow_empty_string)
if isinstance(value, list):
value = [v.lower() for v in value]
if isinstance(value, (str, unicode)):
value = value.lower()
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-----"
if load_pem_x509_certificate is not None:
cert = load_pem_x509_certificate(cert.encode('utf-8'))
else:
cert = load_certificate(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))
sys.exit(0)
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 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)
@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_string=False):
"""
Retrieve value set for module parameter.
Parameters
----------
name: string
The name of the parameter to retrieve.
allow_empty_string: bool
The parameter allowes to have empty strings in a list
"""
return module_params_get(self, name, allow_empty_string)
def params_get_lowercase(self, name, allow_empty_string=False):
"""
Retrieve value set for module parameter as lowercase, if not None.
Parameters
----------
name: string
The name of the parameter to retrieve.
allow_empty_string: bool
The parameter allowes to have empty strings in a list
"""
return module_params_get_lowercase(self, name, allow_empty_string)
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())
return getattr(self, "__ipa_api_domain")
@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)
@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 = inspect.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
class FreeIPABaseModule(IPAAnsibleModule):
"""
Base class for FreeIPA Ansible modules.
Provides methods useful methods to be used by our modules.
This class should be overriten and instantiated for the module.
A basic implementation of an Ansible FreeIPA module expects its
class to:
1. Define a class attribute ``ipa_param_mapping``
2. Implement the method ``define_ipa_commands()``
3. Implement the method ``check_ipa_params()`` (optional)
After instantiating the class the method ``ipa_run()`` should be
called.
Example (ansible-freeipa/plugins/modules/ipasomemodule.py):
class SomeIPAModule(FreeIPABaseModule):
ipa_param_mapping = {
"arg_to_be_passed_to_ipa_command": "module_param",
"another_arg": "get_another_module_param",
}
def get_another_module_param(self):
another_module_param = self.ipa_params.another_module_param
# Validate or modify another_module_param
# ...
return another_module_param
def check_ipa_params(self):
# Validate your params here
# Example:
if not self.ipa_params.module_param in VALID_OPTIONS:
self.fail_json(
msg="Invalid value for argument module_param")
def define_ipa_commands(self):
args = self.get_ipa_command_args()
self.add_ipa_command(
"some_ipa_command",
name="obj-name",
args=args,
)
def main():
ipa_module = SomeIPAModule(argument_spec=dict(
module_param=dict(
type="str",
default=None,
required=False,
),
another_module_param=dict(
type="str",
default=None,
required=False,
),
))
ipa_module.ipa_run()
if __name__ == "__main__":
main()
"""
ipa_param_mapping = None
def __init__(self, *args, **kwargs):
# pylint: disable=super-with-arguments
super(FreeIPABaseModule, self).__init__(*args, **kwargs)
self.deprecate(
msg="FreeIPABaseModule is deprecated. Use IPAAnsibleModule.",
version="1.5.0"
)
# Status of an execution. Will be changed to True
# if something is actually peformed.
self.changed = False
# Status of the connection with the IPA server.
# We need to know if the connection was actually stablished
# before we start sending commands.
self.ipa_connected = False
# Commands to be executed
self.ipa_commands = []
# Module exit arguments.
self.exit_args = {}
def get_ipa_command_args(self, **kwargs):
"""
Return a dict to be passed to an IPA command.
The keys of ``ipa_param_mapping`` are also the keys of the return
dict.
The values of ``ipa_param_mapping`` needs to be either:
* A str with the name of a defined method; or
* A key of ``AnsibleModule.param``.
In case of a method the return of the method will be set as value
for the return dict.
In case of a AnsibleModule.param the value of the param will be
set in the return dict. In addition to that boolean values will be
automaticaly converted to uppercase strings (as required by FreeIPA
server).
"""
self.deprecate(
msg=(
"FreeIPABaseModule is deprecated. Use IPAAnsibleModule. "
"Use 'AnsibleFreeIPAParams.get_ipa_command_args()', "
"Instantiate it using the class 'ipa_params_mapping'."
),
version="1.5.0"
)
mapping = IPAParamMapping(self, self.ipa_param_mapping)
return mapping.get_ipa_command_args(**kwargs)
def check_ipa_params(self):
"""Validate ipa_params before command is called."""
self.deprecate(
msg=(
"FreeIPABaseModule is deprecated. Use IPAAnsibleModule. "
),
version="1.5.0"
)
pass # pylint: disable=unnecessary-pass
def define_ipa_commands(self):
"""Define commands that will be run in IPA server."""
raise NotImplementedError
def add_ipa_command(self, command, name=None, args=None):
"""Add a command to the list of commands to be executed."""
self.ipa_commands.append((name, command, args or {}))
def _run_ipa_commands(self):
"""Execute commands in self.ipa_commands."""
self.changed = self.execute_ipa_commands(
self.ipa_commands,
result_handler=self.process_results.__func__,
exit_args=self.exit_args
)
def process_results(
self, result, command, name, args, exit_args
): # pylint: disable=unused-argument
"""
Process an API command result.
This method must be overriden in subclasses if 'exit_args'
is to be modified.
"""
self.deprecate(
msg=(
"FreeIPABaseModule is deprecated. Use IPAAnsibleModule. "
),
version="1.5.0"
)
self.process_command_result(name, command, args, result)
def process_command_result(self, _name, _command, _args, result):
"""
Process an API command result.
This method can be overriden in subclasses, and
change self.exit_values to return data in the
result for the controller.
"""
self.deprecate(
msg=(
"FreeIPABaseModule is deprecated. Use IPAAnsibleModule. "
"To aid in porting to IPAAnsibleModule, change to "
"'FreeIPABaseModule.process_results'."
),
version="1.5.0"
)
if "completed" in result:
if result["completed"] > 0:
self.changed = True
else:
self.changed = True
def require_ipa_attrs_change(self, command_args, ipa_attrs):
"""
Compare given args with current object attributes.
Returns True in case current IPA object attributes differ from
args passed to the module.
"""
self.deprecate(
msg=(
"FreeIPABaseModule is deprecated. Use IPAAnsibleModule. "
"FreeIPABaseModule require_ipa_attrs_change() is "
"deprecated. Use ansible_freeipa_module.compare_args()."
),
version="1.5.0"
)
equal = compare_args_ipa(self, command_args, ipa_attrs)
return not equal
def ipa_run(self):
"""Execute module actions."""
self.deprecate(
msg=(
"FreeIPABaseModule is deprecated. Use IPAAnsibleModule."
),
version="1.5.0"
)
ipaapi_context = self.params_get("ipaapi_context")
with self.ipa_connect(context=ipaapi_context):
self.check_ipa_params()
self.define_ipa_commands()
self._run_ipa_commands()
self.exit_json(changed=self.changed, **self.exit_args)
ansible-freeipa-v1.7.0/plugins/modules/ 0000775 0000000 0000000 00000000000 14232747165 0020077 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/plugins/modules/README.md 0000664 0000000 0000000 00000001047 14232747165 0021360 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-v1.7.0/plugins/modules/ipaautomember.py 0000664 0000000 0000000 00000052250 14232747165 0023307 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Mark Hahl
# Jake Reynolds
#
# 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: 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: true
aliases: ["cn"]
description:
description: A description of this auto member rule
required: false
automember_type:
description: Grouping to which the rule applies
required: true
type: str
choices: ["group", "hostgroup"]
exclusive:
description: List of dictionaries containing the attribute and expression.
type: list
elements: dict
aliases: ["automemberexclusiveregex"]
options:
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"]
options:
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
required: false
hosts:
description: Hosts to rebuild membership for.
type: list
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
default: automember
choices: ["member", "automember"]
state:
description: State to ensure
default: present
choices: ["present", "absent", "rebuilt", "orphans_removed"]
author:
- Mark Hahl
- Jake Reynolds
- Thomas 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),
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),
expression=dict(type="str", required=True)
),
elements="dict",
required=False),
name=dict(type="list", 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", default=None),
hosts=dict(type="list", 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-v1.7.0/plugins/modules/ipaautomountkey.py 0000664 0000000 0000000 00000015642 14232747165 0023717 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Chris Procter
#
# 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: ipaautomountkey
author: chris procter
short_description: Manage FreeIPA autommount map
description:
- Add, delete, and modify an IPA automount map
options:
ipaadmin_principal:
description: The admin principal
default: admin
ipaadmin_password:
description: The admin password
required: False
location:
description: automount location map is in
required: True
choices: ["automountlocationcn", "automountlocation"]
mapname:
description: automount map to be managed
choices: ["map", "automountmapname", "automountmap"]
required: True
key:
description: automount key to be managed
required: True
choices: ["name", "automountkey"]
newkey:
description: key to change to if state is 'renamed'
required: True
choices: ["newname", "newautomountkey"]
info:
description: Mount information for the key
required: True
choices: ["information", "automountinformation"]
state:
description: State to ensure
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
else:
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=None,
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,
),
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-v1.7.0/plugins/modules/ipaautomountlocation.py 0000664 0000000 0000000 00000007621 14232747165 0024735 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Chris Procter
#
# 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: ipaautomountlocation
author: chris procter
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
aliases: ["cn","location"]
state:
description: State to ensure
required: false
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
else:
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",
aliases=["cn", "location"],
default=None,
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-v1.7.0/plugins/modules/ipaautomountmap.py 0000664 0000000 0000000 00000014223 14232747165 0023676 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Chris Procter
#
# 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: ipaautomountmap
author: Chris Procter
short_description: Manage FreeIPA autommount map
description:
- Add, delete, and modify an IPA automount map
options:
ipaadmin_principal:
description: The admin principal.
default: admin
ipaadmin_password:
description: The admin password.
required: false
automountlocation:
description: automount location map is anchored to
choices: ["location", "automountlocationcn"]
required: True
name:
description: automount map to be managed.
choices: ["mapname", "map", "automountmapname"]
required: True
desc:
description: description of automount map.
choices: ["description"]
required: false
state:
description: State to ensure
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: 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
else:
return response["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'.")
if state == "absent":
if len(name) == 0:
self.fail_json(msg="At least one 'name' must be provided for"
" 'state: absent'")
invalid = ["desc"]
self.params_fail_used_invalid(invalid, state)
def get_args(self, mapname, desc): # pylint: disable=no-self-use
# 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
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")
for mapname in name:
automountmap = self.get_automountmap(location, mapname)
if state == "present":
args = self.get_args(mapname, desc)
if automountmap is None:
self.commands.append([location, "automountmap_add", args])
else:
if not compare_args_ipa(self, args, automountmap):
self.commands.append(
[location, "automountmap_mod", args]
)
if state == "absent":
if automountmap is not None:
self.commands.append([
location,
"automountmap_del",
{"automountmapname": [mapname]}
])
def main():
ipa_module = AutomountMap(
argument_spec=dict(
state=dict(type='str',
default='present',
choices=['present', 'absent']
),
location=dict(type="str",
aliases=["automountlocation", "automountlocationcn"],
default=None,
required=True
),
name=dict(type="list",
aliases=["mapname", "map", "automountmapname"],
default=None,
required=True
),
desc=dict(type="str",
aliases=["description"],
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-v1.7.0/plugins/modules/ipaconfig.py 0000664 0000000 0000000 00000042364 14232747165 0022421 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Chris Procter
#
# 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 __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = '''
---
module: ipa_config
author: chris procter
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
aliases: ['ipamaxusernamelength']
maxhostname:
description: Set the maximum hostname length between 64-255
required: false
aliases: ['ipamaxhostnamelength']
homedirectory:
description: Set the default location of home directories
required: false
aliases: ['ipahomesrootdir']
defaultshell:
description: Set the default shell for new users
required: false
aliases: ['ipadefaultloginshell', 'loginshell']
defaultgroup:
description: Set the default group for new users
required: false
aliases: ['ipadefaultprimarygroup']
emaildomain:
description: Set the default e-mail domain
required: false
aliases: ['ipadefaultemaildomain']
searchtimelimit:
description:
- Set maximum amount of time (seconds) for a search
- values -1 to 2147483647 (-1 or 0 is unlimited)
required: false
aliases: ['ipasearchtimelimit']
searchrecordslimit:
description:
- Set maximum number of records to search
- values -1 to 2147483647 (-1 or 0 is unlimited)
required: false
aliases: ['ipasearchrecordslimit']
usersearch:
description:
- Set comma-separated list of fields to search for user search
required: false
aliases: ['ipausersearchfields']
groupsearch:
description:
- Set comma-separated list of fields to search for group search
required: false
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
aliases: ['ipagroupobjectclasses']
userobjectclasses:
description: Set default user objectclasses (comma-separated list)
required: false
type: list
aliases: ['ipauserobjectclasses']
pwdexpnotify:
description:
- Set number of days's notice of impending password expiration
- values 0 to 2147483647
required: false
aliases: ['ipapwdexpadvnotify']
configstring:
description: Set extra hashes to generate in password plug-in
required: false
type: list
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
aliases: ['ipaselinuxusermaporder']
selinuxusermapdefault:
description: Set default SELinux user when no match found in map rule
required: false
aliases: ['ipaselinuxusermapdefault']
pac_type:
description: set default types of PAC supported for services
required: false
type: list
choices: ["MS-PAC", "PAD", "nfs:NONE", ""]
aliases: ["ipakrbauthzdata"]
user_auth_type:
description: set default types of supported user authentication
required: false
type: list
choices: ["password", "radius", "otp", "disabled", ""]
aliases: ["ipauserauthtype"]
ca_renewal_master_server:
description: Renewal master for IPA certificate authority.
required: false
type: string
domain_resolution_order:
description: set list of domains used for short name qualification
required: false
type: list
aliases: ["ipadomainresolutionorder"]
'''
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
'''
RETURN = '''
config:
description: Dict of all global config options
returned: When no options are set
type: dict
options:
maxusername:
description: maximum username length
returned: always
maxhostname:
description: maximum hostname length
returned: always
homedirectory:
description: default location of home directories
returned: always
defaultshell:
description: default shell for new users
returned: always
defaultgroup:
description: default group for new users
returned: always
emaildomain:
description: default e-mail domain
returned: always
searchtimelimit:
description: maximum amount of time (seconds) for a search
returned: always
searchrecordslimit:
description: maximum number of records to search
returned: always
usersearch:
description: comma-separated list of fields to search in user search
type: list
returned: always
groupsearch:
description: comma-separated list of fields to search in group search
type: list
returned: always
enable_migration:
description: Enable migration mode
type: bool
returned: always
groupobjectclasses:
description: default group objectclasses (comma-separated list)
type: list
returned: always
userobjectclasses:
description: default user objectclasses (comma-separated list)
type: list
returned: always
pwdexpnotify:
description: number of days's notice of impending password expiration
returned: always
configstring:
description: extra hashes to generate in password plug-in
type: list
returned: always
selinuxusermaporder:
description: order in increasing priority of SELinux users
returned: always
selinuxusermapdefault:
description: default SELinux user when no match is found in map rule
returned: always
pac_type:
description: default types of PAC supported for services
type: list
returned: always
user_auth_type:
description: default types of supported user authentication
returned: always
ca_renewal_master_server:
description: master for IPA certificate authority.
returned: always
domain_resolution_order:
description: list of domains used for short name qualification
returned: always
'''
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 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", required=False,
aliases=['ipausersearchfields']),
groupsearch=dict(type="list", required=False,
aliases=['ipagroupsearchfields']),
enable_migration=dict(type="bool", required=False,
aliases=['ipamigrationenabled']),
groupobjectclasses=dict(type="list", required=False,
aliases=['ipagroupobjectclasses']),
userobjectclasses=dict(type="list", required=False,
aliases=['ipauserobjectclasses']),
pwdexpnotify=dict(type="int", required=False,
aliases=['ipapwdexpadvnotify']),
configstring=dict(type="list", 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", required=False,
aliases=['ipaselinuxusermaporder']),
selinuxusermapdefault=dict(type="str", required=False,
aliases=['ipaselinuxusermapdefault']),
pac_type=dict(type="list", required=False,
aliases=["ipakrbauthzdata"],
choices=["MS-PAC", "PAD", "nfs:NONE", ""]),
user_auth_type=dict(type="list", required=False,
choices=["password", "radius", "otp",
"disabled", ""],
aliases=["ipauserauthtype"]),
ca_renewal_master_server=dict(type="str", required=False),
domain_resolution_order=dict(type="list", required=False,
aliases=["ipadomainresolutionorder"])
),
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"
}
allow_empty_string = ["pac_type", "user_auth_type", "configstring"]
reverse_field_map = {v: k for k, v in field_map.items()}
params = {}
for x in field_map:
val = ansible_module.params_get(
x, allow_empty_string=(x in allow_empty_string))
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
with ansible_module.ipa_connect():
result = config_show(ansible_module)
if params:
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"
):
exit_args[k] = (value[0] == "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"] = []
# Done
ansible_module.exit_json(changed=changed, config=exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-v1.7.0/plugins/modules/ipadelegation.py 0000664 0000000 0000000 00000022702 14232747165 0023261 0 ustar 00root root 0000000 0000000 # -*- 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 .
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.
required: true
aliases: ["aciname"]
permission:
description: Permissions to grant (read, write). Default is write.
required: false
aliases: ["permissions"]
attribute:
description: Attribute list to which the delegation applies
required: false
aliases: ["attrs"]
membergroup:
description: User group to apply delegation to
required: false
aliases: ["memberof"]
group:
description: User group ACI grants access to
required: false
action:
description: Work on delegation or member level.
choices: ["delegation", "member"]
default: delegation
required: false
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
required: true
"""
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
else:
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", aliases=["aciname"], default=None,
required=True),
# present
permission=dict(required=False, type='list',
aliases=["permissions"], default=None),
attribute=dict(required=False, type='list', 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("permission")
attribute = ansible_module.params_get("attribute")
membergroup = ansible_module.params_get("membergroup")
group = ansible_module.params_get("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:
# 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 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, "delegation_mod", args])
else:
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))
if len(attrs) > len(res_find["attrs"]):
commands.append([name, "delegation_mod",
{"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.")
# Entries New number of attributes is smaller
if len(attrs) < len(res_find["attrs"]):
commands.append([name, "delegation_mod",
{"attrs": attrs}])
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-v1.7.0/plugins/modules/ipadnsconfig.py 0000664 0000000 0000000 00000017615 14232747165 0023127 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
#
# Copyright (C) 2019 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
options:
ip_address:
description: The forwarder nameserver IP address list (IPv4 and IPv6).
required: true
port:
description: The port to forward requests to.
required: false
forward_policy:
description:
Global forwarding policy. Set to "none" to disable any configured
global forwarders.
required: false
choices: ['only', 'first', 'none']
alias: ["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`.
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`.
default: present
choices: ["present", "absent"]
"""
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:
_args['idnsallowsyncptr'] = 'TRUE' if allow_sync_ptr else 'FALSE'
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', 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"]),
)
)
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-v1.7.0/plugins/modules/ipadnsforwardzone.py 0000664 0000000 0000000 00000032110 14232747165 0024205 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Chris Procter
#
# Copyright (C) 2019 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: ipa_dnsforwardzone
author: chris procter
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.
required: true
aliases: ["cn"]
state:
description: State to ensure
required: false
default: present
choices: ["present", "absent", "enabled", "disabled"]
forwarders:
description:
- List of the DNS servers to forward to
aliases: ["idnsforwarders"]
options:
ip_address:
description: Forwarder IP address (either IPv4 or IPv6).
required: false
type: string
port:
description: Forwarder port.
required: false
type: int
forwardpolicy:
description: Per-zone conditional forwarding policy
required: false
default: only
choices: ["only", "first", "none"]
aliases: ["idnsforwarders", "forward_policy"]
skip_overlap_check:
description:
- Force DNS zone creation even if it will overlap with an existing zone.
required: false
default: false
permission:
description:
- Allow DNS Forward Zone to be managed.
required: false
type: bool
'''
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", aliases=["cn"], default=None,
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:
is_enabled = existing_resource["idnszoneactive"][0]
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-v1.7.0/plugins/modules/ipadnsrecord.py 0000664 0000000 0000000 00000134077 14232747165 0023142 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
#
# 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 __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
options:
name:
description: The DNS record name to manage.
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.
aliases: ["dnszone"]
required: false
record_type:
description: The type of DNS record.
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
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.
required: false
aliases: ["a_record"]
aaaa_rec:
description: Raw AAAA record.
required: false
aliases: ["aaaa_record"]
a6_rec:
description: Raw A6 record.
required: false
aliases: ["a6_record"]
afsdb_rec:
description: Raw AFSDB record.
required: false
aliases: ["afsdb_record"]
cert_rec:
description: Raw CERT record.
required: false
aliases: ["cert_record"]
cname_rec:
description: Raw CNAME record.
required: false
aliases: ["cname_record"]
dlv_rec:
description: Raw DLV record.
required: false
aliases: ["dlv_record"]
dname_rec:
description: Raw DNAM record.
required: false
aliases: ["dname_record"]
ds_rec:
description: Raw DS record.
required: false
aliases: ["ds_record"]
kx_rec:
description: Raw KX record.
required: false
aliases: ["kx_record"]
loc_rec:
description: Raw LOC record.
required: false
aliases: ["loc_record"]
mx_rec:
description: Raw MX record.
required: false
aliases: ["mx_record"]
naptr_rec:
description: Raw NAPTR record.
required: false
aliases: ["naptr_record"]
ns_rec:
description: Raw NS record.
required: false
aliases: ["ns_record"]
ptr_rec:
description: Raw PTR record.
required: false
aliases: ["ptr_record"]
srv_rec:
description: Raw SRV record.
required: false
aliases: ["srv_record"]
sshfp_rec:
description: Raw SSHFP record.
required: false
aliases: ["sshfp_record"]
tlsa_rec:
description: Raw TLSA record.
required: false
aliases: ["tlsa_record"]
txt_rec:
description: Raw TXT record.
required: false
aliases: ["txt_record"]
uri_rec:
description: Raw URI record.
required: false
aliases: ["uri_record"]
ip_address:
description: IP adresses for A or AAAA records.
required: false
type: string
a_ip_address:
description: IP adresses for A records.
required: false
type: string
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: string
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
afsdb_subtype:
description: AFSDB Subtype
required: false
type: int
afsdb_hostname:
description: AFSDB Hostname
required: false
type: string
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: string
cname_hostname:
description: A hostname which this alias hostname points to.
required: false
type: string
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: string
dname_target:
description: DNAME Target
required: false
type: string
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: string
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: string
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"]
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"]
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: string
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: string
naptr_service:
description: NAPTR Service
required: false
type: string
naptr_regexp:
description: NAPTR Regular Expression
required: false
type: string
naptr_replacement:
description: NAPTR Replacement
required: false
type: string
ns_hostname:
description: NS Hostname
required: false
type: string
ptr_hostname:
description: The hostname this reverse record points to.
required: false
type: string
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: string
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: string
txt_data:
description: TXT Text Data
required: false
type: string
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: string
uri_target:
description: Target Uniform Resource Identifier according to RFC 3986.
required: false
type: string
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
zone_name:
description: |
The DNS zone name to which DNS record needs to be managed.
Required if not provided globally.
aliases: ["dnszone"]
required: false
name:
description: The DNS record name to manage.
aliases: ["record_name"]
required: true
record_type:
description: The type of DNS record.
required: false
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 this values.
required: false
type: list
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.
required: false
aliases: ["a_record"]
aaaa_rec:
description: Raw AAAA record.
required: false
aliases: ["aaaa_record"]
a6_rec:
description: Raw A6 record.
required: false
aliases: ["a6_record"]
afsdb_rec:
description: Raw AFSDB record.
required: false
aliases: ["afsdb_record"]
cert_rec:
description: Raw CERT record.
required: false
aliases: ["cert_record"]
cname_rec:
description: Raw CNAME record.
required: false
aliases: ["cname_record"]
dlv_rec:
description: Raw DLV record.
required: false
aliases: ["dlv_record"]
dname_rec:
description: Raw DNAM record.
required: false
aliases: ["dname_record"]
ds_rec:
description: Raw DS record.
required: false
aliases: ["ds_record"]
kx_rec:
description: Raw KX record.
required: false
aliases: ["kx_record"]
loc_rec:
description: Raw LOC record.
required: false
aliases: ["loc_record"]
mx_rec:
description: Raw MX record.
required: false
aliases: ["mx_record"]
naptr_rec:
description: Raw NAPTR record.
required: false
aliases: ["naptr_record"]
ns_rec:
description: Raw NS record.
required: false
aliases: ["ns_record"]
ptr_rec:
description: Raw PTR record.
required: false
aliases: ["ptr_record"]
srv_rec:
description: Raw SRV record.
required: false
aliases: ["srv_record"]
sshfp_rec:
description: Raw SSHFP record.
required: false
aliases: ["sshfp_record"]
tlsa_rec:
description: Raw TLSA record.
required: false
aliases: ["tlsa_record"]
txt_rec:
description: Raw TXT record.
required: false
aliases: ["txt_record"]
uri_rec:
description: Raw URI record.
required: false
aliases: ["uri_record"]
ip_address:
description: IP adresses for A ar AAAA.
required: false
type: string
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"]
a_ip_address:
description: IP adresses for A records.
required: false
type: string
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: string
aaaa_create_reverse:
description: |
Create reverse record for AAAA records.
There is no equivalent to remove reverse records.
type: bool
required: false
afsdb_subtype:
description: AFSDB Subtype
required: false
type: int
afsdb_hostname:
description: AFSDB Hostname
required: false
type: string
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/CRL
required: false
type: string
cname_hostname:
description: A hostname which this alias hostname points to.
required: false
type: string
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: string
dname_target:
description: DNAME Target
required: false
type: string
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: string
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: string
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"]
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"]
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: string
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: string
naptr_service:
description: NAPTR Service
required: false
type: string
naptr_regexp:
description: NAPTR Regular Expression
required: false
type: string
naptr_replacement:
description: NAPTR Replacement
required: false
type: string
ns_hostname:
description: NS Hostname
required: false
type: string
ptr_hostname:
description: The hostname this reverse record points to.
required: false
type: string
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: string
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: string
txt_data:
description: TXT Text Data
required: false
type: string
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: string
uri_target:
description: Target Uniform Resource Identifier according to RFC 3986.
required: false
type: string
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
default: present
choices: ["present", "absent"]
author:
- Rafael Guterres Jeffman
"""
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
import dns.reversename
import dns.resolver
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', required=False),
record_ttl=dict(type='int', required=False),
del_all=dict(type='bool', required=False),
a_rec=dict(type='list', required=False, aliases=['a_record']),
aaaa_rec=dict(type='list', required=False, aliases=['aaaa_record']),
a6_rec=dict(type='list', required=False, aliases=['a6_record']),
afsdb_rec=dict(type='list', required=False, aliases=['afsdb_record']),
cert_rec=dict(type='list', required=False, aliases=['cert_record']),
cname_rec=dict(type='list', required=False, aliases=['cname_record']),
dlv_rec=dict(type='list', required=False, aliases=['dlv_record']),
dname_rec=dict(type='list', required=False, aliases=['dname_record']),
ds_rec=dict(type='list', required=False, aliases=['ds_record']),
kx_rec=dict(type='list', required=False, aliases=['kx_record']),
loc_rec=dict(type='list', required=False, aliases=['loc_record']),
mx_rec=dict(type='list', required=False, aliases=['mx_record']),
naptr_rec=dict(type='list', required=False, aliases=['naptr_record']),
ns_rec=dict(type='list', required=False, aliases=['ns_record']),
ptr_rec=dict(type='list', required=False, aliases=['ptr_record']),
srv_rec=dict(type='list', required=False, aliases=['srv_record']),
sshfp_rec=dict(type='list', required=False, aliases=['sshfp_record']),
tlsa_rec=dict(type='list', required=False, aliases=['tlsa_record']),
txt_rec=dict(type='list', required=False, aliases=['txt_record']),
uri_rec=dict(type='list', 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),
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),
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),
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),
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),
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", aliases=["record_name"], default=None,
required=False),
records=dict(type="list",
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
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 = "{}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:
record_type = field.split('_')[0]
rec = "{}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:
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-v1.7.0/plugins/modules/ipadnszone.py 0000664 0000000 0000000 00000044643 14232747165 0022636 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# 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 __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: true
type: list
alises: ["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
options:
ip_address:
description: The forwarder nameserver IP address list (IPv4 and IPv6).
required: true
port:
description: The port to forward requests to.
required: false
forward_policy:
description:
Global forwarding policy. Set to "none" to disable any configured
global forwarders.
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
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
alises: ["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: bool
allow_query:
description: List of IP addresses or networks which are allowed to issue queries
required: false
type: bool
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
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
""" # 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.
options:
name:
description: The name of the zone created, inferred from `name_from_ip`.
returned: always
"""
from ipapython.dnsutil import DNSName # noqa: E402
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,
) # noqa: E402
import netaddr
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",
# 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)
def is_valid_nsec3param_rec(self, nsec3param_rec): # pylint: disable=R0201
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"]
is_zone_active = "TRUE" in zone.get("idnszoneactive")
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."
)
if self.ipa_params.state != "present":
invalid = ["name_from_ip"]
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)
args = self.ipa_params.get_ipa_command_args(zone=zone)
if self.ipa_params.state in ["present", "enabled", "disabled"]:
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))
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", default=None, required=False, aliases=["zone_name"]
),
name_from_ip=dict(type="str", default=None, required=False),
forwarders=dict(
type="list",
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", required=False, default=None),
allow_query=dict(type="list", 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),
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-v1.7.0/plugins/modules/ipagroup.py 0000664 0000000 0000000 00000054126 14232747165 0022307 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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
required: false
aliases: ["cn"]
description:
description: The group description
required: false
gid:
description: The GID
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
group:
description: List of group names assigned to this group.
required: false
type: list
service:
description:
- List of service names assigned to this group.
- Only usable with IPA versions 4.7 and up.
required: false
type: list
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
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
externalmember:
description:
- List of members of a trusted domain in DOM\\name or name@domain form.
required: false
type: list
ailases: ["ipaexternalmember", "external_member"]
idoverrideuser:
description:
- User ID overrides to add
required: false
type: list
action:
description: Work on group or member level
default: group
choices: ["member", "group"]
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Thomas 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
# 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 sysops
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: ops
group:
- sysops
- appops
# 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
# Remove goups 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
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 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():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", aliases=["cn"], default=None,
required=True),
# 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', default=None),
group=dict(required=False, type='list', default=None),
service=dict(required=False, type='list', default=None),
idoverrideuser=dict(required=False, type='list', default=None),
membermanager_user=dict(required=False, type='list', default=None),
membermanager_group=dict(required=False, type='list',
default=None),
externalmember=dict(required=False, type='list', default=None,
aliases=[
"ipaexternalmember",
"external_member"
]),
action=dict(type="str", default="group",
choices=["member", "group"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
# It does not make sense to set posix, nonposix or external at the
# same time
mutually_exclusive=[['posix', 'nonposix', 'external']],
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")
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("user")
group = ansible_module.params_get("group")
# Services are not case sensitive
service = ansible_module.params_get_lowercase("service")
membermanager_user = ansible_module.params_get("membermanager_user")
membermanager_group = ansible_module.params_get("membermanager_group")
externalmember = ansible_module.params_get("externalmember")
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 group can be added at a time.")
if action == "member":
invalid = ["description", "gid", "posix", "nonposix", "external",
"nomembers"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(
msg="No name given.")
invalid = ["description", "gid", "posix", "nonposix", "external",
"nomembers"]
if action == "group":
invalid.extend(["user", "group", "service", "externalmember"])
ansible_module.params_fail_used_invalid(invalid, state, action)
if external is False:
ansible_module.fail_json(
msg="group can not be non-external")
# 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():
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 = []
for name in names:
# 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")
)
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):
add_member_args["ipaexternalmember"] = \
externalmember_add
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-v1.7.0/plugins/modules/ipahbacrule.py 0000664 0000000 0000000 00000051056 14232747165 0022737 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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
required: true
aliases: ["cn"]
description:
description: The hbacrule description
required: false
usercategory:
description: User category the rule applies to
required: false
aliases: ["usercat"]
choices: ["all", ""]
hostcategory:
description: Host category the rule applies to
required: false
aliases: ["hostcat"]
choices: ["all", ""]
servicecategory:
description: Service category the rule applies to
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
hostgroup:
description: List of host groups assigned to this hbacrule.
required: false
type: list
hbacsvc:
description: List of HBAC service names assigned to this hbacrule.
required: false
type: list
hbacsvcgroup:
description: List of HBAC service names assigned to this hbacrule.
required: false
type: list
user:
description: List of user names assigned to this hbacrule.
required: false
type: list
group:
description: List of user groups assigned to this hbacrule.
required: false
type: list
action:
description: Work on hbacrule or member level
default: hbacrule
choices: ["member", "hbacrule"]
state:
description: State to ensure
default: present
choices: ["present", "absent", "enabled", "disabled"]
author:
- Thomas 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:
return _result["result"][0]
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", aliases=["cn"], default=None,
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', default=None),
hostgroup=dict(required=False, type='list', default=None),
hbacsvc=dict(required=False, type='list', default=None),
hbacsvcgroup=dict(required=False, type='list', default=None),
user=dict(required=False, type='list', default=None),
group=dict(required=False, type='list', 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.
if "ipaenabledflag" not in res_find or \
res_find["ipaenabledflag"][0] != "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 disabled hbacrule
# Therefore it is needed to have a look at the ipaenabledflag
# in res_find.
if "ipaenabledflag" not in res_find or \
res_find["ipaenabledflag"][0] != "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-v1.7.0/plugins/modules/ipahbacsvc.py 0000664 0000000 0000000 00000011517 14232747165 0022561 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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
required: false
aliases: ["cn", "service"]
description:
description: The HBAC Service description
required: false
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Thomas 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", aliases=["cn", "service"], default=None,
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-v1.7.0/plugins/modules/ipahbacsvcgroup.py 0000664 0000000 0000000 00000022306 14232747165 0023634 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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
required: false
aliases: ["cn"]
description:
description: The hbacsvcgroup description
required: false
hbacsvc:
description: List of hbacsvc names assigned to this hbacsvcgroup.
required: false
type: list
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
action:
description: Work on hbacsvcgroup or member level
default: hbacsvcgroup
choices: ["member", "hbacsvcgroup"]
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Thomas 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
# 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.
if "failed" in result and "member" in result["failed"]:
failed = result["failed"]["member"]
for member_type in failed:
for member, failure in failed[member_type]:
if "already a member" not in failure \
and "not a member" not in failure:
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", aliases=["cn"], default=None,
required=True),
# present
description=dict(type="str", default=None),
nomembers=dict(required=False, type='bool', default=None),
hbacsvc=dict(required=False, type='list', 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, result_handler)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-v1.7.0/plugins/modules/ipahost.py 0000664 0000000 0000000 00000162620 14232747165 0022127 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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.
aliases: ["fqdn"]
required: true
hosts:
description: The list of user host dicts
required: false
options:
name:
description: The host (internally uid).
aliases: ["fqdn"]
required: true
description:
description: The host description
required: false
locality:
description: Host locality (e.g. "Baltimore, MD")
required: false
location:
description: Host location (e.g. "Lab 2")
aliases: ["ns_host_location"]
required: false
platform:
description: Host hardware platform (e.g. "Lenovo T61")
aliases: ["ns_hardware_platform"]
required: false
os:
description: Host operating system and version (e.g. "Fedora 9")
aliases: ["ns_os_version"]
required: false
password:
description: Password used in bulk enrollment
aliases: ["user_password", "userpassword"]
required: false
random:
description:
Initiate the generation of a random password to be used in bulk
enrollment
aliases: ["random_password"]
required: false
certificate:
description: List of base-64 encoded host certificates
type: list
aliases: ["usercertificate"]
required: false
managedby_host:
description: List of hosts that can manage this host
type: list
aliases: ["principalname", "krbprincipalname"]
required: false
principal:
description: List of principal aliases for this host
type: list
aliases: ["principalname", "krbprincipalname"]
required: false
allow_create_keytab_user:
description: Users allowed to create a keytab of this host
aliases: ["ipaallowedtoperform_write_keys_user"]
required: false
allow_create_keytab_group:
description: Groups allowed to create a keytab of this host
aliases: ["ipaallowedtoperform_write_keys_group"]
required: false
allow_create_keytab_host:
description: Hosts allowed to create a keytab of this host
aliases: ["ipaallowedtoperform_write_keys_host"]
required: false
allow_create_keytab_hostgroup:
description: Hostgroups allowed to create a keytab of this host
aliases: ["ipaallowedtoperform_write_keys_hostgroup"]
required: false
allow_retrieve_keytab_user:
description: Users allowed to retrieve a keytab of this host
aliases: ["ipaallowedtoperform_read_keys_user"]
required: false
allow_retrieve_keytab_group:
description: Groups allowed to retrieve a keytab of this host
aliases: ["ipaallowedtoperform_read_keys_group"]
required: false
allow_retrieve_keytab_host:
description: Hosts allowed to retrieve a keytab of this host
aliases: ["ipaallowedtoperform_read_keys_host"]
required: false
allow_retrieve_keytab_hostgroup:
description: Hostgroups allowed to retrieve a keytab of this host
aliases: ["ipaallowedtoperform_read_keys_hostgroup"]
required: false
mac_address:
description: List of hardware MAC addresses.
type: list
aliases: ["macaddress"]
required: false
sshpubkey:
description: List of SSH public keys
type: list
aliases: ["ipasshpubkey"]
required: false
userclass:
description:
Host category (semantics placed on this attribute are for local
interpretation)
aliases: ["class"]
required: false
auth_ind:
description:
Defines a whitelist 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
aliases: ["krbprincipalauthind"]
choices: ["radius", "otp", "pkinit", "hardened", ""]
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
required: false
reverse:
description: Reverse DNS detection
default: true
required: false
ip_address:
description:
The host IP address list (IPv4 and IPv6). No IP address conflict
check will be done.
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.
required: false
description:
description: The host description
required: false
locality:
description: Host locality (e.g. "Baltimore, MD")
required: false
location:
description: Host location (e.g. "Lab 2")
aliases: ["ns_host_location"]
required: false
platform:
description: Host hardware platform (e.g. "Lenovo T61")
aliases: ["ns_hardware_platform"]
required: false
os:
description: Host operating system and version (e.g. "Fedora 9")
aliases: ["ns_os_version"]
required: false
password:
description: Password used in bulk enrollment
aliases: ["user_password", "userpassword"]
required: false
random:
description:
Initiate the generation of a random password to be used in bulk
enrollment
aliases: ["random_password"]
required: false
certificate:
description: List of base-64 encoded host certificates
type: list
aliases: ["usercertificate"]
required: false
managedby_host:
description: List of hosts that can manage this host
type: list
aliases: ["principalname", "krbprincipalname"]
required: false
principal:
description: List of principal aliases for this host
type: list
aliases: ["principalname", "krbprincipalname"]
required: false
allow_create_keytab_user:
description: Users allowed to create a keytab of this host
aliases: ["ipaallowedtoperform_write_keys_user"]
required: false
allow_create_keytab_group:
description: Groups allowed to create a keytab of this host
aliases: ["ipaallowedtoperform_write_keys_group"]
required: false
allow_create_keytab_host:
description: Hosts allowed to create a keytab of this host
aliases: ["ipaallowedtoperform_write_keys_host"]
required: false
allow_create_keytab_hostgroup:
description: Hostgroups allowed to create a keytab of this host
aliases: ["ipaallowedtoperform_write_keys_hostgroup"]
required: false
allow_retrieve_keytab_user:
description: Users allowed to retrieve a keytab of this host
aliases: ["ipaallowedtoperform_read_keys_user"]
required: false
allow_retrieve_keytab_group:
description: Groups allowed to retrieve a keytab of this host
aliases: ["ipaallowedtoperform_read_keys_group"]
required: false
allow_retrieve_keytab_host:
description: Hosts allowed to retrieve a keytab of this host
aliases: ["ipaallowedtoperform_read_keys_host"]
required: false
allow_retrieve_keytab_hostgroup:
description: Hostgroups allowed to retrieve a keytab of this host
aliases: ["ipaallowedtoperform_read_keys_hostgroup"]
required: false
mac_address:
description: List of hardware MAC addresses.
type: list
aliases: ["macaddress"]
required: false
sshpubkey:
description: List of SSH public keys
type: list
aliases: ["ipasshpubkey"]
required: false
userclass:
description:
Host category (semantics placed on this attribute are for local
interpretation)
aliases: ["class"]
required: false
auth_ind:
description:
Defines a whitelist 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
aliases: ["krbprincipalauthind"]
choices: ["radius", "otp", "pkinit", "hardened", ""]
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
required: false
reverse:
description: Reverse DNS detection
default: true
required: false
ip_address:
description:
The host IP address list (IPv4 and IPv6). No IP address conflict
check will be done.
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.
required: false
update_password:
description:
Set password for a host in present state only on creation or always
default: 'always'
choices: ["always", "on_create"]
action:
description: Work on host or member level
default: "host"
choices: ["member", "host"]
state:
description: State to ensure
default: present
choices: ["present", "absent",
"disabled"]
author:
- Thomas 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
# 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 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 user did not exist or update_password is yes
type: dict
options:
randompassword:
description: The generated random password
returned: If only one user is handled by the module
name:
description: The user name of the user that got a new random password
returned: If several users are handled by the module
type: dict
options:
randompassword:
description: The generated random password
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)
# pylint: disable=unused-argument
def result_handler(module, result, command, name, args, errors, exit_args,
one_name):
if "random" in args and command in ["host_add", "host_mod"] \
and "randompassword" in result["result"]:
if one_name:
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, one_name):
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", aliases=["usercertificate"],
default=None),
managedby_host=dict(type="list",
default=None),
principal=dict(type="list", aliases=["krbprincipalname"],
default=None),
allow_create_keytab_user=dict(
type="list",
aliases=["ipaallowedtoperform_write_keys_user"],
default=None),
allow_create_keytab_group=dict(
type="list",
aliases=["ipaallowedtoperform_write_keys_group"],
default=None),
allow_create_keytab_host=dict(
type="list",
aliases=["ipaallowedtoperform_write_keys_host"],
default=None),
allow_create_keytab_hostgroup=dict(
type="list",
aliases=["ipaallowedtoperform_write_keys_hostgroup"],
default=None),
allow_retrieve_keytab_user=dict(
type="list",
aliases=["ipaallowedtoperform_write_keys_user"],
default=None),
allow_retrieve_keytab_group=dict(
type="list",
aliases=["ipaallowedtoperform_write_keys_group"],
default=None),
allow_retrieve_keytab_host=dict(
type="list",
aliases=["ipaallowedtoperform_write_keys_host"],
default=None),
allow_retrieve_keytab_hostgroup=dict(
type="list",
aliases=["ipaallowedtoperform_write_keys_hostgroup"],
default=None),
mac_address=dict(type="list", aliases=["macaddress"],
default=None),
sshpubkey=dict(type="str", aliases=["ipasshpubkey"],
default=None),
userclass=dict(type="list", aliases=["class"],
default=None),
auth_ind=dict(type='list', aliases=["krbprincipalauthind"],
default=None,
choices=['radius', 'otp', 'pkinit', 'hardened', '']),
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", 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", 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")
userclass = ansible_module.params_get("userclass")
auth_ind = ansible_module.params_get("auth_ind", allow_empty_string=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
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")
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, one_name=len(names) == 1)
# Done
ansible_module.exit_json(changed=changed, host=exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-v1.7.0/plugins/modules/ipahostgroup.py 0000664 0000000 0000000 00000044414 14232747165 0023204 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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
required: false
aliases: ["cn"]
description:
description: The hostgroup description
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
hostgroup:
description: List of hostgroup names assigned to this hostgroup.
required: false
type: list
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
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
rename:
description:
- Rename hostgroup to the given name.
- Only usable with IPA versions 4.8.7 and up.
required: false
aliases: ["new_name"]
action:
description: Work on hostgroup or member level
default: hostgroup
choices: ["member", "hostgroup"]
state:
description: State to ensure
default: present
choices: ["present", "absent", "renamed"]
author:
- Thomas 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 gen_member_args(host, hostgroup):
_args = {}
if host is not None:
_args["member_host"] = host
if hostgroup is not None:
_args["member_hostgroup"] = hostgroup
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", aliases=["cn"], default=None,
required=True),
# present
description=dict(type="str", default=None),
nomembers=dict(required=False, type='bool', default=None),
host=dict(required=False, type='list', default=None),
hostgroup=dict(required=False, type='list', default=None),
membermanager_user=dict(required=False, type='list', default=None),
membermanager_group=dict(required=False, type='list',
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("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("hostgroup")
membermanager_user = ansible_module.params_get("membermanager_user")
membermanager_group = ansible_module.params_get("membermanager_group")
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 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:
# 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 = {}
member_args = gen_member_args(host, hostgroup)
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("member_host"))
hostgroup_add, hostgroup_del = gen_add_del_lists(
hostgroup, res_find.get("member_hostgroup"))
# Add members
if len(host_add) > 0 or len(hostgroup_add) > 0:
commands.append([name, "hostgroup_add_member",
{
"host": host_add,
"hostgroup": hostgroup_add,
}])
# Remove members
if len(host_del) > 0 or len(hostgroup_del) > 0:
commands.append([name, "hostgroup_remove_member",
{
"host": host_del,
"hostgroup": hostgroup_del,
}])
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")
)
if has_add_membermanager:
# Add membermanager users and groups
if len(membermanager_user_add) > 0 or \
len(membermanager_group_add) > 0:
commands.append(
[name, "hostgroup_add_member_manager",
{
"user": membermanager_user_add,
"group": membermanager_group_add,
}]
)
# Remove member manager
if len(membermanager_user_del) > 0 or \
len(membermanager_group_del) > 0:
commands.append(
[name, "hostgroup_remove_member_manager",
{
"user": membermanager_user_del,
"group": membermanager_group_del,
}]
)
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.
if host is not None and "member_host" in res_find:
host = gen_add_list(host, res_find["member_host"])
if hostgroup is not None \
and "member_hostgroup" in res_find:
hostgroup = gen_add_list(
hostgroup, res_find["member_hostgroup"])
# Ensure members are present
commands.append([name, "hostgroup_add_member",
{
"host": host,
"hostgroup": hostgroup,
}])
if has_add_membermanager:
# Reduce add list for membermanager_user and
# membermanager_group to new entries only that are
# not in res_find.
if membermanager_user is not None \
and "membermanager_user" in res_find:
membermanager_user = gen_add_list(
membermanager_user,
res_find["membermanager_user"])
if membermanager_group is not None \
and "membermanager_group" in res_find:
membermanager_group = gen_add_list(
membermanager_group,
res_find["membermanager_group"])
# Add membermanager users and groups
if membermanager_user is not None or \
membermanager_group is not None:
commands.append(
[name, "hostgroup_add_member_manager",
{
"user": membermanager_user,
"group": 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 = gen_intersection_list(
host, res_find.get("member_host"))
if hostgroup is not None:
hostgroup = gen_intersection_list(
hostgroup, res_find.get("member_hostgroup"))
# Ensure members are absent
commands.append([name, "hostgroup_remove_member",
{
"host": host,
"hostgroup": hostgroup,
}])
if has_add_membermanager:
# Reduce del lists of membermanager_user and
# membermanager_group to the entries only that are
# in res_find.
if membermanager_user is not None:
membermanager_user = gen_intersection_list(
membermanager_user,
res_find.get("membermanager_user"))
if membermanager_group is not None:
membermanager_group = gen_intersection_list(
membermanager_group,
res_find.get("membermanager_group"))
# Remove membermanager users and groups
if membermanager_user is not None or \
membermanager_group is not None:
commands.append(
[name, "hostgroup_remove_member_manager",
{
"user": membermanager_user,
"group": membermanager_group,
}]
)
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-v1.7.0/plugins/modules/ipaidrange.py 0000664 0000000 0000000 00000024510 14232747165 0022556 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
#
# 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.
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: string
required: false
choices: ["ipa-ad-trust", "ipa-ad-trust-posix", "ipa-local"]
aliases: ["iparangetype"]
dom_sid:
description: Domain SID of the trusted domain.
type: string
required: false
aliases: ["ipanttrusteddomainsid"]
dom_name:
description: Domain name of the trusted domain.
type: string
required: false
aliases: ["ipanttrusteddomainname"]
auto_private_groups:
description: Auto creation of private groups.
type: string
required: false
choices: ["true", "false", "hybrid"]
aliases: ["ipaautoprivategroups"]
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
required: true
"""
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
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
else:
return _result["result"]
def gen_args(
base_id, range_size, rid_base, secondary_rid_base, idrange_type, dom_sid,
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_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", aliases=["cn"],
default=None, 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")
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"]
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, 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-v1.7.0/plugins/modules/ipalocation.py 0000664 0000000 0000000 00000011474 14232747165 0022762 0 ustar 00root root 0000000 0000000 # -*- 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 .
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.
required: true
aliases: ["idnsname"]
description:
description: The IPA location string
required: false
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
required: true
"""
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
else:
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", aliases=["idnsname"],
default=None, 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-v1.7.0/plugins/modules/ipapermission.py 0000664 0000000 0000000 00000041252 14232747165 0023337 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Seth Kress
#
# 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 __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.
required: true
aliases: ["cn"]
right:
description: Rights to grant
required: false
choices: ["read", "search", "compare", "write", "add", "delete", "all"]
type: list
aliases: ["ipapermright"]
attrs:
description: All attributes to which the permission applies
required: false
type: list
bindtype:
description: Bind rule type
required: false
choices: ["permission", "all", "anonymous"]
aliases: ["ipapermbindruletype"]
subtree:
description: Subtree to apply permissions to
required: false
aliases: ["ipapermlocation"]
filter:
description: Extra target filter
required: false
type: list
aliases: ["extratargetfilter"]
rawfilter:
description: All target filters
required: false
type: list
aliases: ["ipapermtargetfilter"]
target:
description: Optional DN to apply the permission to
required: false
aliases: ["ipapermtarget"]
targetto:
description: Optional DN subtree where an entry can be moved to
required: false
aliases: ["ipapermtargetto"]
targetfrom:
description: Optional DN subtree from where an entry can be moved
required: false
aliases: ["ipapermtargetfrom"]
memberof:
description: Target members of a group (sets memberOf targetfilter)
required: false
type: list
targetgroup:
description: User group to apply permissions to (sets target)
required: false
aliases: ["targetgroup"]
object_type:
description: Type of IPA object (sets subtree and objectClass targetfilter)
required: false
aliases: ["type"]
no_members:
description: Suppress processing of membership
required: false
type: bool
rename:
description: Rename the permission object
required: false
aliases: ["new_name"]
action:
description: Work on permission or member privilege level.
choices: ["permission", "member"]
default: permission
required: false
state:
description: The state to ensure.
choices: ["present", "absent", "renamed"]
default: present
required: true
"""
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
else:
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", aliases=["cn"],
default=None, required=True),
# present
right=dict(type="list", aliases=["ipapermright"], default=None,
required=False,
choices=["read", "search", "compare", "write", "add",
"delete", "all"]),
attrs=dict(type="list", default=None, required=False),
# Note: bindtype has a default of permission for Adds.
bindtype=dict(type="str", aliases=["ipapermbindruletype"],
default=None, require=False, choices=["permission",
"all", "anonymous", "self"]),
subtree=dict(type="str", aliases=["ipapermlocation"], default=None,
required=False),
extra_target_filter=dict(type="list", aliases=["filter",
"extratargetfilter"], default=None,
required=False),
rawfilter=dict(type="list", 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", 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, require=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-v1.7.0/plugins/modules/ipaprivilege.py 0000664 0000000 0000000 00000023073 14232747165 0023136 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
#
# 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 __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.
required: true
aliases: ["cn"]
description:
description: Privilege description
required: false
rename:
description: Rename the privilege object.
required: false
aliases: ["new_name"]
permission:
description: Permissions to be added to the privilege.
required: false
action:
description: Work on privilege or member level.
choices: ["privilege", "member"]
default: privilege
required: false
state:
description: The state to ensure.
choices: ["present", "absent", "renamed"]
default: present
required: true
"""
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
else:
return _result["result"]
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", aliases=["cn"],
default=None, 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', 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-v1.7.0/plugins/modules/ipapwpolicy.py 0000664 0000000 0000000 00000020623 14232747165 0023014 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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
options:
ipaadmin_principal:
description: The admin principal
default: admin
ipaadmin_password:
description: The admin password
required: false
name:
description: The group name
required: false
aliases: ["cn"]
maxlife:
description: Maximum password lifetime (in days)
type: int
required: false
aliases: ["krbmaxpwdlife"]
minlife:
description: Minimum password lifetime (in hours)
type: int
required: false
aliases: ["krbminpwdlife"]
history:
description: Password history size
type: int
required: false
aliases: ["krbpwdhistorylength"]
minclasses:
description: Minimum number of character classes
type: int
required: false
aliases: ["krbpwdmindiffchars"]
minlength:
description: Minimum length of password
type: int
required: false
aliases: ["krbpwdminlength"]
priority:
description: Priority of the policy (higher number means lower priority)
type: int
required: false
aliases: ["cospriority"]
maxfail:
description: Consecutive failures before lockout
type: int
required: false
aliases: ["krbpwdmaxfailure"]
failinterval:
description: Period after which failure count will be reset (seconds)
type: int
required: false
aliases: ["krbpwdfailurecountinterval"]
lockouttime:
description: Period for which lockout is enforced (seconds)
type: int
required: false
aliases: ["krbpwdlockoutduration"]
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Thomas Woerner
"""
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(maxlife, minlife, history, minclasses, minlength, priority,
maxfail, failinterval, lockouttime):
_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
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", aliases=["cn"], default=None,
required=False),
# present
maxlife=dict(type="int", aliases=["krbmaxpwdlife"], default=None),
minlife=dict(type="int", aliases=["krbminpwdlife"], default=None),
history=dict(type="int", aliases=["krbpwdhistorylength"],
default=None),
minclasses=dict(type="int", aliases=["krbpwdmindiffchars"],
default=None),
minlength=dict(type="int", aliases=["krbpwdminlength"],
default=None),
priority=dict(type="int", aliases=["cospriority"], default=None),
maxfail=dict(type="int", aliases=["krbpwdmaxfailure"],
default=None),
failinterval=dict(type="int",
aliases=["krbpwdfailurecountinterval"],
default=None),
lockouttime=dict(type="int", aliases=["krbpwdlockoutduration"],
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("maxlife")
minlife = ansible_module.params_get("minlife")
history = ansible_module.params_get("history")
minclasses = ansible_module.params_get("minclasses")
minlength = ansible_module.params_get("minlength")
priority = ansible_module.params_get("priority")
maxfail = ansible_module.params_get("maxfail")
failinterval = ansible_module.params_get("failinterval")
lockouttime = ansible_module.params_get("lockouttime")
# 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"]
ansible_module.params_fail_used_invalid(invalid, state)
# Init
changed = False
exit_args = {}
with ansible_module.ipa_connect():
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(maxlife, minlife, history, minclasses,
minlength, priority, maxfail, failinterval,
lockouttime)
# 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-v1.7.0/plugins/modules/iparole.py 0000664 0000000 0000000 00000033454 14232747165 0022115 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
"""ansible-freeipa iparole module implementation."""
# Authors:
# Rafael Guterres Jeffman
#
# 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 __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:
role:
description: The list of role name strings.
required: true
aliases: ["cn"]
description:
description: A description for the role.
required: false
rename:
description: Rename the role object.
required: false
aliases: ["new_name"]
user:
description: List of users.
required: false
group:
description: List of groups.
required: false
host:
description: List of hosts.
required: false
hostgroup:
description: List of hostgroups.
required: false
service:
description: List of services.
required: false
action:
description: Work on role or member level.
choices: ["role", "member"]
default: role
required: false
state:
description: The state to ensure.
choices: ["present", "absent", "renamed"]
default: present
required: true
"""
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
else:
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", aliases=["cn"], default=None,
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', default=None),
user=dict(required=False, type='list', default=None),
group=dict(required=False, type='list', default=None),
host=dict(required=False, type='list', default=None),
hostgroup=dict(required=False, type='list', default=None),
service=dict(required=False, type='list', 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-v1.7.0/plugins/modules/ipaselfservice.py 0000664 0000000 0000000 00000022030 14232747165 0023452 0 ustar 00root root 0000000 0000000 # -*- 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 .
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.
required: true
aliases: ["aciname"]
permission:
description: Permissions to grant (read, write). Default is write.
required: false
aliases: ["permissions"]
attribute:
description: Attribute list to which the selfservice applies
required: false
aliases: ["attrs"]
action:
description: Work on selfservice or member level.
choices: ["selfservice", "member"]
default: selfservice
required: false
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
required: true
"""
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
else:
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", aliases=["aciname"], default=None,
required=True),
# present
permission=dict(required=False, type='list',
aliases=["permissions"], default=None),
attribute=dict(required=False, type='list', 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-v1.7.0/plugins/modules/ipaserver.py 0000664 0000000 0000000 00000031715 14232747165 0022460 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
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.
required: true
aliases: ["cn"]
location:
description: |
The server location string.
"" for location reset.
Only in state: present.
required: false
aliases: ["ipalocation_location"]
service_weight:
description: |
Weight for server services
Values 0 to 65535, -1 for weight reset.
Only in state: present.
required: false
type: int
aliases: ["ipaserviceweight"]
hidden:
description: |
Set hidden state of a server.
Only in state: present.
required: false
type: bool
no_members:
description: |
Suppress processing of membership attributes
Only in state: present.
required: false
type: bool
delete_continue:
description: |
Continuous mode: Don't stop on errors.
Only in 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 in state: absent.
required: false
type: bool
ignore_topology_disconnect:
description: |
Ignore topology connectivity problems after removal.
Only in state: absent.
required: false
type: bool
force:
description: |
Force server removal even if it does not exist.
Will always result in changed.
Only in state: absent.
required: false
type: bool
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
required: true
"""
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
else:
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
else:
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", aliases=["cn"],
default=None, 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-v1.7.0/plugins/modules/ipaservice.py 0000664 0000000 0000000 00000063415 14232747165 0022614 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
#
# Copyright (C) 2019 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
required: true
aliases: ["service"]
certificate:
description: Base-64 encoded service certificate.
required: false
type: list
aliases: ["usercertificate"]
pac_type:
description: Supported PAC type.
required: false
choices: ["MS-PAC", "PAD", "NONE", ""]
type: list
aliases: ["pac_type", "ipakrbauthzdata"]
auth_ind:
description: Defines a whitelist for Authentication Indicators.
required: false
choices: ["otp", "radius", "pkinit", "hardened", ""]
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
default: False
aliases: ["ipakrbrequirespreauth"]
ok_as_delegate:
description: Client credentials may be delegated to the service.
required: false
type: bool
default: False
aliases: ["ipakrbokasdelegate"]
ok_to_auth_as_delegate:
description: Allow service to authenticate on behalf of a client.
required: false
type: bool
default: False
aliases: ["ipakrboktoauthasdelegate"]
principal:
description: List of principal aliases for the service.
required: false
type: list
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
aliases: ["managedby_host"]
allow_create_keytab_user:
description: Users allowed to create a keytab of this host.
required: false
type: list
aliases: ["ipaallowedtoperform_write_keys_user"]
allow_create_keytab_group:
description: Groups allowed to create a keytab of this host.
required: false
type: list
aliases: ["ipaallowedtoperform_write_keys_group"]
allow_create_keytab_host:
description: Hosts allowed to create a keytab of this host.
required: false
type: list
aliases: ["ipaallowedtoperform_write_keys_host"]
allow_create_keytab_hostgroup:
description: Host group allowed to create a keytab of this host.
required: false
type: list
aliases: ["ipaallowedtoperform_write_keys_hostgroup"]
allow_retrieve_keytab_user:
description: User allowed to retrieve a keytab of this host.
required: false
type: list
aliases: ["ipaallowedtoperform_read_keys_user"]
allow_retrieve_keytab_group:
description: Groups allowed to retrieve a keytab of this host.
required: false
type: list
aliases: ["ipaallowedtoperform_read_keys_group"]
allow_retrieve_keytab_host:
description: Hosts allowed to retrieve a keytab of this host.
required: false
type: list
aliases: ["ipaallowedtoperform_read_keys_host"]
allow_retrieve_keytab_hostgroup:
description: Host groups allowed to retrieve a keytab of this host.
required: false
type: list
aliases: ["ipaallowedtoperform_read_keys_hostgroup"]
continue:
description:
Continuous mode. Don't stop on errors. Valid only if `state` is `absent`.
required: false
default: True
type: bool
action:
description: Work on service or member level
default: service
choices: ["member", "service"]
state:
description: State to ensure
default: present
choices: ["present", "absent", "disabled"]
author:
- Rafael Jeffman
"""
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
"""
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
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 len(names) != 1:
module.fail_json(msg="Only one service can be added at a time.")
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 len(names) < 1:
module.fail_json(msg="No name given.")
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 init_ansible_module():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", aliases=["service"], default=None,
required=True),
# service attributesstr
certificate=dict(type="list", aliases=['usercertificate'],
default=None, required=False),
principal=dict(type="list", aliases=["krbprincipalname"],
default=None),
smb=dict(type="bool", required=False),
netbiosname=dict(type="str", required=False),
pac_type=dict(type="list", aliases=["ipakrbauthzdata"],
choices=["MS-PAC", "PAD", "NONE", ""]),
auth_ind=dict(type="list",
aliases=["krbprincipalauthind"],
choices=["otp", "radius", "pkinit", "hardened", ""]),
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", aliases=["managedby_host"], required=False),
allow_create_keytab_user=dict(
type="list", required=False,
aliases=['ipaallowedtoperform_write_keys_user']),
allow_retrieve_keytab_user=dict(
type="list", required=False,
aliases=['ipaallowedtoperform_read_keys_user']),
allow_create_keytab_group=dict(
type="list", required=False,
aliases=['ipaallowedtoperform_write_keys_group']),
allow_retrieve_keytab_group=dict(
type="list", required=False,
aliases=['ipaallowedtoperform_read_keys_group']),
allow_create_keytab_host=dict(
type="list", required=False,
aliases=['ipaallowedtoperform_write_keys_host']),
allow_retrieve_keytab_host=dict(
type="list", required=False,
aliases=['ipaallowedtoperform_read_keys_host']),
allow_create_keytab_hostgroup=dict(
type="list", required=False,
aliases=['ipaallowedtoperform_write_keys_hostgroup']),
allow_retrieve_keytab_hostgroup=dict(
type="list", required=False,
aliases=['ipaallowedtoperform_read_keys_hostgroup']),
delete_continue=dict(type="bool", required=False,
aliases=['continue']),
# action
action=dict(type="str", default="service",
choices=["member", "service"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent", "disabled"]),
),
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")
# service attributes
principal = ansible_module.params_get("principal")
certificate = ansible_module.params_get("certificate")
pac_type = ansible_module.params_get("pac_type", allow_empty_string=True)
auth_ind = ansible_module.params_get("auth_ind", allow_empty_string=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
check_parameters(ansible_module, state, action, names)
# 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")
commands = []
keytab_members = ["user", "group", "host", "hostgroup"]
for name in names:
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-v1.7.0/plugins/modules/ipaservicedelegationrule.py 0000664 0000000 0000000 00000027420 14232747165 0025534 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.
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.
required: false
target:
description: |
The list of service delegation targets.
required: false
aliases: ["servicedelegationtarget"]
action:
description: Work on servicedelegationrule or member level.
choices: ["servicedelegationrule", "member"]
default: servicedelegationrule
required: false
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
required: true
"""
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
else:
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", aliases=["cn"], default=None,
required=True),
# present
principal=dict(required=False, type='list', default=None),
target=dict(required=False, type='list',
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-v1.7.0/plugins/modules/ipaservicedelegationtarget.py 0000664 0000000 0000000 00000021312 14232747165 0026045 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.
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.
required: false
action:
description: Work on servicedelegationtarget or member level.
choices: ["servicedelegationtarget", "member"]
default: servicedelegationtarget
required: false
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
required: true
"""
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
else:
return _result["result"]
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", aliases=["cn"], default=None,
required=True),
# present
principal=dict(required=False, type='list', 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-v1.7.0/plugins/modules/ipasudocmd.py 0000664 0000000 0000000 00000011122 14232747165 0022576 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
#
# Copyright (C) 2019 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
required: true
aliases: ["sudocmd"]
description:
description: The command description
required: false
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Rafael Jeffman
"""
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", aliases=["sudocmd"], default=None,
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-v1.7.0/plugins/modules/ipasudocmdgroup.py 0000664 0000000 0000000 00000022025 14232747165 0023657 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
#
# Copyright (C) 2019 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
required: false
aliases: ["cn"]
description:
description: The sudocmdgroup description
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
action:
description: Work on sudocmdgroup or member level
default: hostgroup
choices: ["member", "sudocmdgroup"]
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Rafael Guterres Jeffman
"""
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
else:
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", aliases=["cn"], default=None,
required=True),
# present
description=dict(type="str", default=None),
nomembers=dict(required=False, type='bool', default=None),
sudocmd=dict(required=False, type='list', 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-v1.7.0/plugins/modules/ipasudorule.py 0000664 0000000 0000000 00000076056 14232747165 0023023 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
#
# Copyright (C) 2019 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
required: true
aliases: ["cn"]
description:
description: The sudorule description
required: false
user:
description: List of users assigned to the sudo rule.
required: false
usercategory:
description: User category the sudo rule applies to
required: false
choices: ["all", ""]
aliases: ["usercat"]
group:
description: List of user groups assigned to the sudo rule.
required: false
runasgroupcategory:
description: RunAs Group category applied to the sudo rule.
required: false
choices: ["all", ""]
aliases: ["runasgroupcat"]
runasusercategory:
description: RunAs User category applied to the sudorule.
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
hostgroup:
description: List of host groups assigned to this sudorule.
required: false
type: list
hostcategory:
description: Host category the sudo rule applies to.
required: false
choices: ["all", ""]
aliases: ["hostcat"]
allow_sudocmd:
description: List of allowed sudocmds assigned to this sudorule.
required: false
type: list
allow_sudocmdgroup:
description: List of allowed sudocmd groups assigned to this sudorule.
required: false
type: list
deny_sudocmd:
description: List of denied sudocmds assigned to this sudorule.
required: false
type: list
deny_sudocmdgroup:
description: List of denied sudocmd groups assigned to this sudorule.
required: false
type: list
cmdcategory:
description: Command category the sudo rule applies to
required: false
choices: ["all", ""]
aliases: ["cmdcat"]
order:
description: Order to apply this rule.
required: false
type: int
sudooption:
description: List of sudo options.
required: false
type: list
aliases: ["options"]
runasuser:
description: List of users for Sudo to execute as.
required: false
type: list
runasgroup:
description: List of groups for Sudo to execute as.
required: false
type: list
action:
description: Work on sudorule or member level
default: sudorule
choices: ["member", "sudorule"]
state:
description: State to ensure
default: present
choices: ["present", "absent", "enabled", "disabled"]
author:
- Rafael Jeffman
"""
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"
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allusers
usercategory: all
action: enabled
# Ensure sudo rule for hostcategory "all"
- ipasudorule:
ipaadmin_password: SomeADMINpassword
name: allhosts
hostcategory: all
action: enabled
# 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
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", aliases=["cn"], default=None,
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', default=None),
hostgroup=dict(required=False, type='list', default=None),
user=dict(required=False, type='list', default=None),
group=dict(required=False, type='list', default=None),
allow_sudocmd=dict(required=False, type="list", default=None),
deny_sudocmd=dict(required=False, type="list", default=None),
allow_sudocmdgroup=dict(required=False, type="list", default=None),
deny_sudocmdgroup=dict(required=False, type="list", 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", default=None),
runasgroup=dict(required=False, type="list", default=None),
order=dict(type="int", required=False, aliases=['sudoorder']),
sudooption=dict(required=False, type='list', 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")
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")
runasgroup = ansible_module.params_get_lowercase("runasgroup")
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 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", "user", "group",
"runasuser", "runasgroup", "allow_sudocmd",
"allow_sudocmdgroup", "deny_sudocmd",
"deny_sudocmdgroup", "sudooption"])
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",
"user", "group", "allow_sudocmd", "allow_sudocmdgroup",
"deny_sudocmd", "deny_sudocmdgroup", "runasuser",
"runasgroup", "order", "sudooption"]
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 = [], []
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 = [], []
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', []))
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', [])
)
)
# 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 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', [])))
)
# 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 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', []))
)
)
# 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.
if "ipaenabledflag" not in res_find or \
res_find["ipaenabledflag"][0] != "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.
if "ipaenabledflag" not in res_find or \
res_find["ipaenabledflag"][0] != "FALSE":
commands.append([name, "sudorule_disable", {}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Manage members.
# Manage hosts and hostgroups
if host_add or hostgroup_add:
commands.append([name, "sudorule_add_host",
{
"host": host_add,
"hostgroup": hostgroup_add,
}])
if host_del or hostgroup_del:
commands.append([name, "sudorule_remove_host",
{
"host": host_del,
"hostgroup": hostgroup_del,
}])
# 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:
commands.append([
name, "sudorule_add_runasuser", {"user": runasuser_add}
])
if runasuser_del:
commands.append([
name, "sudorule_remove_runasuser", {"user": runasuser_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-v1.7.0/plugins/modules/ipatopologysegment.py 0000664 0000000 0000000 00000026074 14232747165 0024413 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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
required: true
choices: ["domain", "ca", "domain+ca"]
name:
description: Topology segment name, unique identifier.
required: false
aliases: ["cn"]
left:
description: Left replication node - an IPA server
aliases: ["leftnode"]
right:
description: Right replication node - an IPA server
aliases: ["rightnode"]
direction:
description: The direction a segment will be reinitialized
required: false
choices: ["left-to-right", "right-to-left"]
state:
description: State to ensure
default: present
choices: ["present", "absent", "enabled", "disabled", "reinitialized",
"checked" ]
author:
- Thomas 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(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-v1.7.0/plugins/modules/ipatopologysuffix.py 0000664 0000000 0000000 00000004725 14232747165 0024254 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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
required: true
choices: ["domain", "ca"]
state:
description: State to ensure
default: verified
choices: ["verified"]
author:
- Thomas 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(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-v1.7.0/plugins/modules/ipatrust.py 0000664 0000000 0000000 00000017653 14232747165 0022340 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rob Verduijn
#
# Copyright (C) 2019 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
required: true
trust_type:
description:
- Trust type (ad for Active Directory, default)
default: ad
required: false
choices: ["ad"]
admin:
description:
- Active Directory domain administrator
required: false
password:
description:
- Active Directory domain administrator's password
required: false
server:
description:
- Domain controller for the Active Directory domain (optional)
required: false
trust_secret:
description:
- Shared secret for the trust
required: false
base_id:
description:
- First Posix ID of the range reserved for the trusted domain
required: false
range_size:
description:
- Size of the ID range reserved for the trusted domain
range_type:
description:
- Type of trusted domain ID range, one of ipa-ad-trust, ipa-ad-trust-posix
default: ipa-ad-trust
required: false
two_way:
description:
- Establish bi-directional trust. By default trust is inbound one-way only.
default: false
required: false
choices: ["true", "false"]
external:
description:
- Establish external trust to a domain in another forest.
- The trust is not transitive beyond the domain.
default: false
required: false
choices: ["true", "false"]
state:
description: State to ensure
default: present
required: true
choices: ["present", "absent"]
author:
- Rob Verduijn
"""
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", default=None, 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-v1.7.0/plugins/modules/ipauser.py 0000664 0000000 0000000 00000150610 14232747165 0022124 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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).
required: false
users:
description: The list of user dicts (internally uid).
options:
name:
description: The user (internally uid).
required: true
first:
description: The first name
required: false
aliases: ["givenname"]
last:
description: The last name
required: false
aliases: ["sn"]
fullname:
description: The full name
required: false
aliases: ["cn"]
displayname:
description: The display name
required: false
initials:
description: Initials
required: false
homedir:
description: The home directory
required: false
shell:
description: The login shell
required: false
aliases: ["loginshell"]
email:
description: List of email addresses
required: false
principal:
description: The kerberos principal
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.
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.
required: false
aliases: ["krbpasswordexpiration"]
password:
description: The user password
required: false
random:
description: Generate a random user password
required: false
type: bool
uid:
description: The UID
required: false
aliases: ["uidnumber"]
gid:
description: The GID
required: false
aliases: ["gidnumber"]
city:
description: City
required: false
userstate:
description: State/Province
required: false
aliases: ["st"]
postalcode:
description: Postalcode/ZIP
required: false
aliases: ["zip"]
phone:
description: List of telephone numbers
required: false
aliases: ["telephonenumber"]
mobile:
description: List of mobile telephone numbers
required: false
pager:
description: List of pager numbers
required: false
fax:
description: List of fax numbers
required: false
aliases: ["facsimiletelephonenumber"]
orgunit:
description: Org. Unit
required: false
title:
description: The job title
required: false
manager:
description: List of managers
required: false
carlicense:
description: List of car licenses
required: false
sshpubkey:
description: List of SSH public keys
required: false
aliases: ["ipasshpubkey"]
userauthtype:
description:
List of supported user authentication types
Use empty string to reset userauthtype to the initial value.
choices: ['password', 'radius', 'otp', '']
required: false
aliases: ["ipauserauthtype"]
userclass:
description:
- User category
- (semantics placed on this attribute are for local interpretation)
required: false
radius:
description: RADIUS proxy configuration
required: false
radiususer:
description: RADIUS proxy username
required: false
departmentnumber:
description: Department Number
required: false
employeenumber:
description: Employee Number
required: false
employeetype:
description: Employee Type
required: false
preferredlanguage:
description: Preferred Language
required: false
certificate:
description: List of base-64 encoded user certificates
required: false
certmapdata:
description:
- List of certificate mappings
- Only usable with IPA versions 4.5 and up.
options:
certificate:
description: Base-64 encoded user certificate
required: false
issuer:
description: Issuer of the certificate
required: false
subject:
description: Subject of the certificate
required: false
data:
description: Certmap data
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
required: false
first:
description: The first name
required: false
aliases: ["givenname"]
last:
description: The last name
required: false
aliases: ["sn"]
fullname:
description: The full name
required: false
aliases: ["cn"]
displayname:
description: The display name
required: false
initials:
description: Initials
required: false
homedir:
description: The home directory
required: false
shell:
description: The login shell
required: false
aliases: ["loginshell"]
email:
description: List of email addresses
required: false
principal:
description: The kerberos principal
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.
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.
required: false
aliases: ["krbpasswordexpiration"]
password:
description: The user password
required: false
random:
description: Generate a random user password
required: false
type: bool
uid:
description: The UID
required: false
aliases: ["uidnumber"]
gid:
description: The GID
required: false
aliases: ["gidnumber"]
city:
description: City
required: false
userstate:
description: State/Province
required: false
aliases: ["st"]
postalcode:
description: ZIP
required: false
aliases: ["zip"]
phone:
description: List of telephone numbers
required: false
aliases: ["telephonenumber"]
mobile:
description: List of mobile telephone numbers
required: false
pager:
description: List of pager numbers
required: false
fax:
description: List of fax numbers
required: false
aliases: ["facsimiletelephonenumber"]
orgunit:
description: Org. Unit
required: false
title:
description: The job title
required: false
manager:
description: List of managers
required: false
carlicense:
description: List of car licenses
required: false
sshpubkey:
description: List of SSH public keys
required: false
aliases: ["ipasshpubkey"]
userauthtype:
description:
List of supported user authentication types
Use empty string to reset userauthtype to the initial value.
choices: ['password', 'radius', 'otp', '']
required: false
aliases: ["ipauserauthtype"]
userclass:
description:
- User category
- (semantics placed on this attribute are for local interpretation)
required: false
radius:
description: RADIUS proxy configuration
required: false
radiususer:
description: RADIUS proxy username
required: false
departmentnumber:
description: Department Number
required: false
employeenumber:
description: Employee Number
required: false
employeetype:
description: Employee Type
required: false
preferredlanguage:
description: Preferred Language
required: false
certificate:
description: List of base-64 encoded user certificates
required: false
certmapdata:
description:
- List of certificate mappings
- Only usable with IPA versions 4.5 and up.
options:
certificate:
description: Base-64 encoded user certificate
required: false
issuer:
description: Issuer of the certificate
required: false
subject:
description: Subject of the certificate
required: false
data:
description: Certmap data
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
preserve:
description: Delete a user, keeping the entry available for future use
required: false
update_password:
description:
Set password for a user in present state only on creation or always
default: "always"
choices: ["always", "on_create"]
required: false
action:
description: Work on user or member level
default: "user"
choices: ["member", "user"]
state:
description: State to ensure
default: present
choices: ["present", "absent",
"enabled", "disabled",
"unlocked", "undeleted"]
author:
- Thomas 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
# 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 user pinky and brain
- ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky,brain
state: disabled
"""
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
options:
randompassword:
description: The generated random password
returned: If only one user is handled by the module
name:
description: The user name of the user that got a new random password
returned: If several users are handled by the module
type: dict
options:
randompassword:
description: The generated random password
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, shell,
email, principalexpiration, passwordexpiration, password,
random, uid, gid, city, userstate, postalcode, phone, mobile,
pager, fax, orgunit, title, carlicense, sshpubkey, userauthtype,
userclass, radius, radiususer, departmentnumber, employeenumber,
employeetype, preferredlanguage, 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 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 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 noprivate is not None:
_args["noprivate"] = noprivate
if nomembers is not None:
_args["no_members"] = nomembers
return _args
def check_parameters( # pylint: disable=unused-argument
module, state, action, first, last, fullname, displayname, initials,
homedir, shell, email, principal, principalexpiration,
passwordexpiration, password, random, uid, gid, 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):
invalid = []
if state == "present":
if action == "member":
invalid = ["first", "last", "fullname", "displayname", "initials",
"homedir", "shell", "email", "principalexpiration",
"passwordexpiration", "password", "random", "uid",
"gid", "city", "phone", "mobile", "pager", "fax",
"orgunit", "title", "carlicense", "sshpubkey",
"userauthtype", "userclass", "radius", "radiususer",
"departmentnumber", "employeenumber", "employeetype",
"preferredlanguage", "noprivate", "nomembers",
"preserve", "update_password"]
else:
invalid = ["first", "last", "fullname", "displayname", "initials",
"homedir", "shell", "email", "principalexpiration",
"passwordexpiration", "password", "random", "uid",
"gid", "city", "phone", "mobile", "pager", "fax",
"orgunit", "title", "carlicense", "sshpubkey",
"userauthtype", "userclass", "radius", "radiususer",
"departmentnumber", "employeenumber", "employeetype",
"preferredlanguage", "noprivate", "nomembers",
"update_password"]
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")
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 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,
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"]
# 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, one_name):
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),
shell=dict(type="str", aliases=["loginshell"], default=None),
email=dict(type="list", default=None),
principal=dict(type="list", aliases=["principalname",
"krbprincipalname"],
default=None),
principalexpiration=dict(type="str",
aliases=["krbprincipalexpiration"],
default=None),
passwordexpiration=dict(type="str",
aliases=["krbpasswordexpiration"],
default=None),
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),
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", aliases=["telephonenumber"], default=None),
mobile=dict(type="list", default=None),
pager=dict(type="list", default=None),
fax=dict(type="list", aliases=["facsimiletelephonenumber"],
default=None),
orgunit=dict(type="str", aliases=["ou"], default=None),
title=dict(type="str", default=None),
manager=dict(type="list", default=None),
carlicense=dict(type="list", default=None),
sshpubkey=dict(type="list", aliases=["ipasshpubkey"],
default=None),
userauthtype=dict(type='list', aliases=["ipauserauthtype"],
default=None,
choices=['password', 'radius', 'otp', '']),
userclass=dict(type="list", 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", default=None),
employeenumber=dict(type="str", default=None),
employeetype=dict(type="str", default=None),
preferredlanguage=dict(type="str", default=None),
certificate=dict(type="list", 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),
)
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", aliases=["login"], default=None,
required=False),
users=dict(type="list",
aliases=["login"],
default=None,
options=dict(
# Here name is a simple string
name=dict(type="str", required=True),
# 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"]),
# 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")
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")
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_string=True)
userauthtype = ansible_module.params_get("userauthtype",
allow_empty_string=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")
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")
# 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 == "present":
if names is not None and len(names) != 1:
ansible_module.fail_json(
msg="Only one user can be added at a time using name.")
check_parameters(
ansible_module, state, action,
first, last, fullname, displayname, initials, homedir, shell, email,
principal, principalexpiration, passwordexpiration, password, random,
uid, gid, 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)
certmapdata = convert_certmapdata(certmapdata)
# Use users if names is None
if users is not None:
names = users
# 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()
# 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")
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")
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")
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,
shell, email, principal, principalexpiration,
passwordexpiration, password, random, uid, gid, 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)
certmapdata = convert_certmapdata(certmapdata)
# 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")
# 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,
shell, email, principalexpiration, passwordexpiration,
password, random, uid, gid, city, userstate, postalcode,
phone, mobile, pager, fax, orgunit, title, carlicense,
sshpubkey, userauthtype, userclass, radius, radiususer,
departmentnumber, employeenumber, employeetype,
preferredlanguage, 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 "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")
commands.append([name, "user_add", args])
# 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)
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, one_name=len(names) == 1)
# Done
ansible_module.exit_json(changed=changed, user=exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-v1.7.0/plugins/modules/ipavault.py 0000664 0000000 0000000 00000110203 14232747165 0022273 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman
#
# Copyright (C) 2019 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
required: true
aliases: ["cn"]
description:
description: The vault description
required: false
public_key:
description: Base64 encode public key.
required: false
type: string
aliases: ["ipavaultpublickey", "vault_public_key"]
public_key_file:
description: Path to file with public key.
required: false
type: string
aliases: ["vault_public_key_file"]
private_key:
description: Base64 encode private key.
required: false
type: string
aliases: ["ipavaultprivatekey", "vault_private_key"]
private_key_file:
description: Path to file with private key.
required: false
type: string
aliases: ["vault_private_key_file"]
password:
description: password to be used on symmetric vault.
required: false
type: string
aliases: ["ipavaultpassword", "vault_password", "old_password"]
password_file:
description: file with password to be used on symmetric vault.
required: false
type: string
aliases: ["vault_password_file", "old_password_file"]
new_password:
description: new password to be used on symmetric vault.
required: false
type: string
new_password_file:
description: file with new password to be used on symmetric vault.
required: false
type: string
salt:
description: Vault salt.
required: false
type: list
aliases: ["ipavaultsalt", "vault_salt"]
vault_type:
description: Vault types are based on security level.
required: true
default: symmetric
choices: ["standard", "symmetric", "asymmetric"]
aliases: ["ipavaulttype"]
service:
description: Any service can own one or more service vaults.
required: false
type: list
username:
description: Any user can own one or more user vaults.
required: false
type: string
aliases: ["user"]
shared:
description: Vault is shared.
required: false
type: boolean
users:
description: Users that are member of the vault.
required: false
type: list
groups:
description: Groups that are member of the vault.
required: false
type: list
owners:
description: Users that are owners of the vault.
required: false
type: list
aliases: ["ownerusers"]
ownergroups:
description: Groups that are owners of the vault.
required: false
type: list
ownerservices:
description: Services that are owners of the vault.
required: false
type: list
services:
description: Services that are member of the container.
required: false
type: list
data:
description: Data to be stored in the vault.
required: false
type: string
aliases: ["ipavaultdata", "vault_data"]
in:
description: Path to file with data to be stored in the vault.
required: false
type: string
aliases: ["datafile_in"]
out:
description: Path to file to store data retrieved from the vault.
required: false
type: string
aliases: ["datafile_out"]
action:
description: Work on vault or member level.
default: vault
choices: ["vault", "member"]
state:
description: State to ensure
default: present
choices: ["present", "absent", "retrieved"]
author:
- Rafael Jeffman
"""
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
options:
data:
description: The vault data.
returned: always
type: string
"""
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", aliases=["cn"], default=None,
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', default=None),
groups=dict(required=False, type='list', default=None),
services=dict(required=False, type='list', default=None),
owners=dict(required=False, type='list', default=None,
aliases=['ownerusers']),
ownergroups=dict(required=False, type='list', default=None),
ownerservices=dict(required=False, type='list', 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:
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:
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:
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-v1.7.0/pytest.ini 0000664 0000000 0000000 00000000211 14232747165 0016771 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-v1.7.0/requirements-dev.txt 0000664 0000000 0000000 00000000110 14232747165 0020776 0 ustar 00root root 0000000 0000000 -r requirements-tests.txt
ipdb
pre-commit
flake8-bugbear
pylint==2.12.2
ansible-freeipa-v1.7.0/requirements-tests.txt 0000664 0000000 0000000 00000000162 14232747165 0021371 0 ustar 00root root 0000000 0000000 -r requirements.txt
pytest>=2.7
pytest-sourceorder>=0.5
pytest-split-tests>=1.0.3
pytest-testinfra>=5.0
pyyaml>=3
ansible-freeipa-v1.7.0/requirements.txt 0000664 0000000 0000000 00000000000 14232747165 0020220 0 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ 0000775 0000000 0000000 00000000000 14232747165 0016072 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipabackup/ 0000775 0000000 0000000 00000000000 14232747165 0020031 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipabackup/README.md 0000664 0000000 0000000 00000023361 14232747165 0021315 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+
* Fedora 26+
* Ubuntu
Requirements
------------
**Controller**
* Ansible version: 2.8+
**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-v1.7.0/roles/ipabackup/defaults/ 0000775 0000000 0000000 00000000000 14232747165 0021640 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipabackup/defaults/main.yml 0000664 0000000 0000000 00000000516 14232747165 0023311 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-v1.7.0/roles/ipabackup/library/ 0000775 0000000 0000000 00000000000 14232747165 0021475 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipabackup/library/ipabackup_get_backup_dir.py 0000664 0000000 0000000 00000003406 14232747165 0027033 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
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
options:
author:
- Thomas 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
from ipaplatform.paths import paths
def main():
module = AnsibleModule(
argument_spec={},
supports_check_mode=True,
)
module.exit_json(changed=False,
backup_dir=paths.IPA_BACKUP_DIR)
if __name__ == '__main__':
main()
ansible-freeipa-v1.7.0/roles/ipabackup/meta/ 0000775 0000000 0000000 00000000000 14232747165 0020757 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipabackup/meta/main.yml 0000664 0000000 0000000 00000000521 14232747165 0022424 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.8
platforms:
- name: Fedora
versions:
- all
- name: EL
versions:
- 7
- 8
galaxy_tags:
- identity
- ipa
- freeipa
ansible-freeipa-v1.7.0/roles/ipabackup/tasks/ 0000775 0000000 0000000 00000000000 14232747165 0021156 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipabackup/tasks/backup.yml 0000664 0000000 0000000 00000002553 14232747165 0023153 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipabackup
- name: Create backup
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
- block:
- name: Get ipabackup_item from stderr or stdout output
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
fail: msg="Failed to get ipabackup_item"
when: ipabackup_item is not defined
- name: Copy backup to controller
include_tasks: "{{ role_path }}/tasks/copy_backup_from_server.yml"
when: state|default("present") == "present"
- name: Remove backup on server
include_tasks: "{{ role_path }}/tasks/remove_backup_from_server.yml"
when: not ipabackup_keep_on_server
when: ipabackup_to_controller
ansible-freeipa-v1.7.0/roles/ipabackup/tasks/copy_backup_from_server.yml 0000664 0000000 0000000 00000002645 14232747165 0026620 0 ustar 00root root 0000000 0000000 ---
- name: Fail on invalid ipabackup_item
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
set_fact:
ipabackup_controller_dir:
"{{ ipabackup_controller_path | default(lookup('env','PWD')) }}/{{
ipabackup_name_prefix | default(ansible_facts['fqdn']) }}_{{
ipabackup_item }}/"
- name: Stat backup on server
stat:
path: "{{ ipabackup_dir }}/{{ ipabackup_item }}"
register: result_backup_stat
- name: Fail on missing backup directory
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 }}"
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
fetch:
flat: yes
src: "{{ ipabackup_dir }}/{{ ipabackup_item }}/{{ item }}"
dest: "{{ ipabackup_controller_dir }}"
with_items:
- "{{ result_find_backup_files.stdout_lines }}"
- name: Fix file modes for backup on controller
file:
dest: "{{ ipabackup_controller_dir }}"
mode: u=rwX,go=
recurse: yes
delegate_to: localhost
become: no
ansible-freeipa-v1.7.0/roles/ipabackup/tasks/copy_backup_to_server.yml 0000664 0000000 0000000 00000002454 14232747165 0026275 0 ustar 00root root 0000000 0000000 ---
- name: Fail on invalid ipabackup_name
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
set_fact:
ipabackup_controller_dir:
"{{ ipabackup_controller_path | default(lookup('env','PWD')) }}"
- name: Set ipabackup_item
set_fact:
ipabackup_item:
"{{ ipabackup_name | regex_search('.*_(ipa-.+)','\\1') | first }}"
when: "'_ipa-' in ipabackup_name"
- name: Set ipabackup_item
set_fact:
ipabackup_item: "{{ ipabackup_name }}"
when: "'_ipa-' not in ipabackup_name"
- name: Stat backup to copy
stat:
path: "{{ ipabackup_controller_dir }}/{{ ipabackup_name }}"
register: result_backup_stat
delegate_to: localhost
become: no
- name: Fail on missing backup to copy
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 }}"
copy:
src: "{{ ipabackup_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-v1.7.0/roles/ipabackup/tasks/get_ipabackup_dir.yml 0000664 0000000 0000000 00000000346 14232747165 0025340 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
set_fact:
ipabackup_dir: "{{ result_ipabackup_get_backup_dir.backup_dir }}"
ansible-freeipa-v1.7.0/roles/ipabackup/tasks/main.yml 0000664 0000000 0000000 00000011345 14232747165 0022631 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipabackup
- name: Check for empty vars
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
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
fail: msg="ipabackup_from_controller and ipabackup_to_controller are set"
when: ipabackup_from_controller | bool and ipabackup_to_controller | bool
- name: Get ipabackup_dir from IPA installation
include_tasks: "{{ role_path }}/tasks/get_ipabackup_dir.yml"
- name: Backup IPA server
include_tasks: "{{ role_path }}/tasks/backup.yml"
when: state|default("present") == "present"
- name: Fail for given ipabackup_name if state is not copied, restored or absent
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: Fail on missing ipabackup_name
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")
- block:
- name: Get list of all backups on IPA server
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
set_fact:
ipabackup_names: "{{ result_backup_find_backup_files.stdout_lines }}"
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: Fail on ipabackup_name all
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
set_fact:
ipabackup_names: ["{{ ipabackup_name }}"]
when: ipabackup_name | type_debug != "list"
- name: Set ipabackup_names from ipabackup_name list
set_fact:
ipabackup_names: "{{ ipabackup_name }}"
when: ipabackup_name | type_debug == "list"
when: ipabackup_names is not defined and ipabackup_name is defined
- name: Set empty ipabackup_names if ipabackup_name is not defined
set_fact:
ipabackup_names: []
when: ipabackup_names is not defined and ipabackup_name is not defined
- block:
- name: Copy backup from IPA server
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
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"
when: state is defined and
((state == "copied" and ipabackup_to_controller) or 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
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.
- block:
- name: Copy backup to server
include_tasks: "{{ role_path }}/tasks/copy_backup_to_server.yml"
- name: Restore IPA server after copy
include_tasks: "{{ role_path }}/tasks/restore.yml"
when: state|default("present") == "restored"
vars:
ipabackup_name: "{{ ipabackup_names[0] }}"
when: ipabackup_from_controller or
(state|default("present") == "copied" and not ipabackup_to_controller)
- name: Restore IPA server
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-v1.7.0/roles/ipabackup/tasks/remove_backup_from_server.yml 0000664 0000000 0000000 00000000200 14232747165 0027124 0 ustar 00root root 0000000 0000000 ---
- name: Remove backup "{{ ipabackup_item }}"
file:
path: "{{ ipabackup_dir }}/{{ ipabackup_item }}"
state: absent
ansible-freeipa-v1.7.0/roles/ipabackup/tasks/restore.yml 0000664 0000000 0000000 00000012506 14232747165 0023370 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipabackup
### VARIABLES
- name: Import variables specific to distribution
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
stat:
path: "{{ ipabackup_dir }}/{{ ipabackup_item }}"
register: result_backup_stat
- name: Fail on missing backup directory
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 }}"
stat:
path: "{{ ipabackup_dir }}/{{ ipabackup_item }}/header"
register: result_backup_header_stat
- name: Fail on missing header file in backup
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
shell: >
grep "^services = " "{{ ipabackup_dir }}/{{ ipabackup_item }}/header" | cut -d"=" -f2 | tr -d '[:space:]'
register: result_services_grep
- name: Set ipabackup_services
set_fact:
ipabackup_services: "{{ result_services_grep.stdout.split(',') }}"
ipabackup_service_dns: DNS
ipabackup_service_adtrust: ADTRUST
ipabackup_service_ntp: NTP
### INSTALL PACKAGES
- block:
- name: Ensure that IPA server packages are installed
package:
name: "{{ ipaserver_packages }}"
state: present
- name: Ensure that IPA server packages for dns are installed
package:
name: "{{ ipaserver_packages_dns }}"
state: present
when: ipabackup_service_dns in ipabackup_services
- name: Ensure that IPA server packages for adtrust are installed
package:
name: "{{ ipaserver_packages_adtrust }}"
state: present
when: ipabackup_service_adtrust in ipabackup_services
- name: Ensure that firewalld packages are installed
package:
name: "{{ ipaserver_packages_firewalld }}"
state: present
when: ipabackup_setup_firewalld | bool
when: ipabackup_install_packages | bool
### START FIREWALLD
- block:
- name: Ensure that firewalld is running
systemd:
name: firewalld
enabled: yes
state: started
- name: Firewalld - Verify runtime zone "{{ ipabackup_firewalld_zone }}"
shell: >
firewall-cmd
--info-zone="{{ ipabackup_firewalld_zone }}"
>/dev/null
when: ipabackup_firewalld_zone is defined
- name: Firewalld - Verify permanent zone "{{ ipabackup_firewalld_zone }}"
shell: >
firewall-cmd
--permanent
--info-zone="{{ ipabackup_firewalld_zone }}"
>/dev/null
when: ipabackup_firewalld_zone is defined
when: ipabackup_setup_firewalld | bool
### RESTORE
- name: Restore backup
no_log: True
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
debug:
msg: "{{ result_iparestore.stderr }}"
when: result_iparestore is failed
failed_when: yes
### CONFIGURE FIREWALLD
- name: Configure firewalld
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
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-v1.7.0/roles/ipabackup/vars/ 0000775 0000000 0000000 00000000000 14232747165 0021004 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipabackup/vars/Fedora.yml 0000664 0000000 0000000 00000000366 14232747165 0022734 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-v1.7.0/roles/ipabackup/vars/RedHat-7.yml 0000664 0000000 0000000 00000000401 14232747165 0023035 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-v1.7.0/roles/ipabackup/vars/RedHat-8.yml 0000664 0000000 0000000 00000000354 14232747165 0023045 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-v1.7.0/roles/ipabackup/vars/Ubuntu-18.04.yml 0000664 0000000 0000000 00000000674 14232747165 0023470 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-v1.7.0/roles/ipabackup/vars/Ubuntu.yml 0000664 0000000 0000000 00000000366 14232747165 0023016 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-v1.7.0/roles/ipabackup/vars/default.yml 0000664 0000000 0000000 00000000357 14232747165 0023160 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-v1.7.0/roles/ipaclient/ 0000775 0000000 0000000 00000000000 14232747165 0020042 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaclient/README.md 0000664 0000000 0000000 00000026154 14232747165 0021331 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
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+
* Fedora 26+
* Ubuntu
Requirements
------------
**Controller**
* Ansible version: 2.8+
* /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)
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
```
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_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
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
Authors
=======
Florence Blanc-Renaud
Thomas Woerner
ansible-freeipa-v1.7.0/roles/ipaclient/action_plugins/ 0000775 0000000 0000000 00000000000 14232747165 0023060 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaclient/action_plugins/ipaclient_get_otp.py 0000664 0000000 0000000 00000020131 14232747165 0027120 0 ustar 00root root 0000000 0000000 # Authors:
# Florence Blanc-Renaud
#
# Copyright (C) 2017 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
import os
import shutil
import subprocess
import tempfile
from jinja2 import Template
from ansible.errors import AnsibleError
from ansible.module_utils._text import to_native
from ansible.plugins.action import ActionBase
def run_cmd(args, stdin=None):
"""Execute an external command."""
p_in = None
p_out = subprocess.PIPE
p_err = subprocess.PIPE
if stdin:
p_in = subprocess.PIPE
# pylint: disable=invalid-name
with subprocess.Popen(
args, stdin=p_in, stdout=p_out, stderr=p_err, close_fds=True
) as p:
__temp, stderr = p.communicate(stdin)
if p.returncode != 0:
raise RuntimeError(stderr)
def kinit_password(principal, password, ccache_name, config):
"""
Perform kinit using principal/password.
It uses the specified config file to kinit and stores the TGT
in ccache_name.
"""
args = ["/usr/bin/kinit", principal, '-c', ccache_name]
old_config = os.environ.get('KRB5_CONFIG')
os.environ['KRB5_CONFIG'] = config
try:
return run_cmd(args, stdin=password.encode())
finally:
if old_config is not None:
os.environ['KRB5_CONFIG'] = old_config
else:
os.environ.pop('KRB5_CONFIG', None)
def kinit_keytab(principal, keytab, ccache_name, config):
"""
Perform kinit using principal/keytab.
It uses the specified config file to kinit and stores the TGT
in ccache_name.
"""
args = ["/usr/bin/kinit", "-kt", keytab, "-c", ccache_name, principal]
old_config = os.environ.get('KRB5_CONFIG')
os.environ["KRB5_CONFIG"] = config
try:
return run_cmd(args)
finally:
if old_config is not None:
os.environ["KRB5_CONFIG"] = old_config
else:
os.environ.pop("KRB5_CONFIG", None)
KRB5CONF_TEMPLATE = """
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = {{ ipa_realm }}
dns_lookup_realm = false
dns_lookup_kdc = true
rdns = false
ticket_lifetime = {{ ipa_lifetime }}
forwardable = true
udp_preference_limit = 0
default_ccache_name = KEYRING:persistent:%{uid}
[realms]
{{ ipa_realm }} = {
kdc = {{ ipa_server }}:88
master_kdc = {{ ipa_server }}:88
admin_server = {{ ipa_server }}:749
default_domain = {{ ipa_domain }}
}
[domain_realm]
.{{ ipa_domain }} = {{ ipa_realm }}
{{ ipa_domain }} = {{ ipa_realm }}
"""
class ActionModule(ActionBase): # pylint: disable=too-few-public-methods
# pylint: disable=too-many-return-statements
def run(self, tmp=None, task_vars=None):
"""
Handle credential cache transfer.
ipa* commands can either provide a password or a keytab file
in order to authenticate on the managed node with Kerberos.
The module is using these credentials to obtain a TGT locally on the
control node:
- need to create a krb5.conf Kerberos client configuration that is
using IPA server
- set the environment variable KRB5_CONFIG to point to this conf file
- set the environment variable KRB5CCNAME to use a specific cache
- perform kinit on the control node
This command creates the credential cache file
- copy the credential cache file on the managed node
Then the IPA commands can use this credential cache file.
"""
if task_vars is None:
task_vars = {}
# pylint: disable=super-with-arguments
result = super(ActionModule, self).run(tmp, task_vars)
principal = self._task.args.get('principal', None)
keytab = self._task.args.get('keytab', None)
password = self._task.args.get('password', None)
lifetime = self._task.args.get('lifetime', '1h')
if (not keytab and not password):
result['failed'] = True
result['msg'] = "keytab or password is required"
return result
if not principal:
result['failed'] = True
result['msg'] = "principal is required"
return result
data = self._execute_module(module_name='ipaclient_get_facts',
module_args={}, task_vars=task_vars)
try:
domain = data['ansible_facts']['ipa']['domain']
realm = data['ansible_facts']['ipa']['realm']
except KeyError:
result['failed'] = True
result['msg'] = "The host is not an IPA server"
return result
items = principal.split('@')
if len(items) < 2:
principal = str('%s@%s' % (principal, realm))
# Locally create a temp directory to store krb5.conf and ccache
local_temp_dir = tempfile.mkdtemp()
krb5conf_name = os.path.join(local_temp_dir, 'krb5.conf')
ccache_name = os.path.join(local_temp_dir, 'ccache')
# Create the krb5.conf from the template
template = Template(KRB5CONF_TEMPLATE)
content = template.render(dict(
ipa_server=task_vars['ansible_host'],
ipa_domain=domain,
ipa_realm=realm,
ipa_lifetime=lifetime))
with open(krb5conf_name, 'w') as f: # pylint: disable=invalid-name
f.write(content)
if password:
try:
# perform kinit -c ccache_name -l 1h principal
kinit_password(principal, password, ccache_name,
krb5conf_name)
except Exception as e:
result['failed'] = True
result['msg'] = 'kinit %s with password failed: %s' % \
(principal, to_native(e))
return result
else:
# Password not supplied, need to use the keytab file
# Check if the source keytab exists
try:
keytab = self._find_needle('files', keytab)
except AnsibleError as e:
result['failed'] = True
result['msg'] = to_native(e)
return result
# perform kinit -kt keytab
try:
kinit_keytab(principal, keytab, ccache_name, krb5conf_name)
except Exception as e:
result['failed'] = True
result['msg'] = 'kinit %s with keytab %s failed: %s' % \
(principal, keytab, str(e))
return result
try:
# Create the remote tmp dir
tmp = self._make_tmp_path()
tmp_ccache = self._connection._shell.join_path(
tmp, os.path.basename(ccache_name))
# Copy the ccache to the remote tmp dir
self._transfer_file(ccache_name, tmp_ccache)
self._fixup_perms2((tmp, tmp_ccache))
new_module_args = self._task.args.copy()
new_module_args.pop('password', None)
new_module_args.pop('keytab', None)
new_module_args.pop('lifetime', None)
new_module_args.update(ccache=tmp_ccache)
# Execute module
result.update(self._execute_module(module_args=new_module_args,
task_vars=task_vars))
return result
finally:
# delete the local temp directory
shutil.rmtree(local_temp_dir, ignore_errors=True)
ansible-freeipa-v1.7.0/roles/ipaclient/defaults/ 0000775 0000000 0000000 00000000000 14232747165 0021651 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaclient/defaults/main.yml 0000664 0000000 0000000 00000001302 14232747165 0023314 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_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
ansible-freeipa-v1.7.0/roles/ipaclient/library/ 0000775 0000000 0000000 00000000000 14232747165 0021506 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaclient/library/ipaclient_api.py 0000664 0000000 0000000 00000017645 14232747165 0024676 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: no
debug:
description: Turn on extra debugging
required: yes
author:
- Thomas 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
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: string
sample: O=EXAMPLE.COM
'''
import os
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging,
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
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list'),
realm=dict(required=True),
hostname=dict(required=True),
debug=dict(required=False, type='bool', default="false"),
),
supports_check_mode=True,
)
module._ansible_debug = True
setup_logging()
realm = module.params.get('realm')
hostname = module.params.get('hostname')
debug = module.params.get('debug')
host_principal = 'host/%s@%s' % (hostname, realm)
os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
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 = inspect.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: {}".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-v1.7.0/roles/ipaclient/library/ipaclient_fix_ca.py 0000664 0000000 0000000 00000007451 14232747165 0025350 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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: Repair Fix IPA ca certificate
options:
servers:
description: Fully qualified name of IPA servers to enroll to
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
basedn:
description: The basedn of the IPA server (of the form dc=example,dc=com)
required: no
allow_repair:
description: |
Allow repair of already joined hosts. Contrary to ipaclient_force_join
the host entry will not be changed on the server
required: no
author:
- Thomas 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
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging,
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'),
realm=dict(required=True),
basedn=dict(required=True),
allow_repair=dict(required=True, type='bool'),
),
)
module._ansible_debug = True
setup_logging()
servers = module.params.get('servers')
realm = module.params.get('realm')
basedn = module.params.get('basedn')
allow_repair = module.params.get('allow_repair')
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
del os.environ['KRB5_CONFIG']
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-v1.7.0/roles/ipaclient/library/ipaclient_fstore.py 0000664 0000000 0000000 00000003774 14232747165 0025425 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
author:
- Thomas 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, paths, sysrestore
)
def main():
module = AnsibleModule(
argument_spec=dict(
backup=dict(required=True),
),
)
module._ansible_debug = True
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-v1.7.0/roles/ipaclient/library/ipaclient_get_facts.py 0000664 0000000 0000000 00000013166 14232747165 0026056 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = """
---
module: ipaclient_get_facts
short description: Get facts about IPA client and server configuration.
description: Get facts about IPA client and server configuration.
author:
- Thomas Woerner
"""
import os
import re
from ansible.module_utils import six
try:
from ansible.module_utils.six.moves.configparser import RawConfigParser
except ImportError:
from ConfigParser import RawConfigParser
from ansible.module_utils.basic import AnsibleModule
# pylint: disable=unused-import
try:
from ipalib import api # noqa: F401
except ImportError:
HAS_IPALIB = False
else:
HAS_IPALIB = True
from ipaplatform.paths import paths
try:
# FreeIPA >= 4.5
from ipalib.install import sysrestore
except ImportError:
# FreeIPA 4.4 and older
from ipapython import sysrestore
try:
import ipaserver # noqa: F401
except ImportError:
HAS_IPASERVER = False
else:
HAS_IPASERVER = True
SERVER_SYSRESTORE_STATE = "/var/lib/ipa/sysrestore/sysrestore.state"
NAMED_CONF = "/etc/named.conf"
VAR_LIB_PKI_TOMCAT = "/var/lib/pki/pki-tomcat"
def is_ntpd_configured():
# ntpd is configured when sysrestore.state contains the line
# [ntpd]
ntpd_conf_section = re.compile(r'^\s*\[ntpd\]\s*$')
try:
# pylint: disable=invalid-name
with open(SERVER_SYSRESTORE_STATE) as f:
for line in f.readlines():
if ntpd_conf_section.match(line):
return True
# pylint: enable=invalid-name
return False
except IOError:
return False
def is_dns_configured():
# dns is configured when /etc/named.conf contains the line
# dyndb "ipa" "/usr/lib64/bind/ldap.so" {
bind_conf_section = re.compile(r'^\s*dyndb\s+"ipa"\s+"[^"]+"\s+{$')
try:
with open(NAMED_CONF) as f: # pylint: disable=invalid-name
for line in f.readlines():
if bind_conf_section.match(line):
return True
return False
except IOError:
return False
def is_dogtag_configured(subsystem):
# ca / kra is configured when the directory
# /var/lib/pki/pki-tomcat/[ca|kra] # exists
available_subsystems = {'ca', 'kra'}
if subsystem not in available_subsystems:
raise AssertionError("Subsystem '%s' not available" % subsystem)
return os.path.isdir(os.path.join(VAR_LIB_PKI_TOMCAT, subsystem))
def is_ca_configured():
return is_dogtag_configured('ca')
def is_kra_configured():
return is_dogtag_configured('kra')
def is_client_configured():
# IPA Client is configured when /etc/ipa/default.conf exists
# and /var/lib/ipa-client/sysrestore/sysrestore.state exists
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
return os.path.isfile(paths.IPA_DEFAULT_CONF) and fstore.has_files()
def is_server_configured():
# IPA server is configured when /etc/ipa/default.conf exists
# and /var/lib/ipa/sysrestore/sysrestore.state exists
return (os.path.isfile(paths.IPA_DEFAULT_CONF) and
os.path.isfile(SERVER_SYSRESTORE_STATE))
def get_ipa_conf():
# Extract basedn, realm and domain from /etc/ipa/default.conf
parser = RawConfigParser()
parser.read(paths.IPA_DEFAULT_CONF)
basedn = parser.get('global', 'basedn')
realm = parser.get('global', 'realm')
domain = parser.get('global', 'domain')
return dict(
basedn=basedn,
realm=realm,
domain=domain
)
def get_ipa_version():
try:
# pylint: disable=import-outside-toplevel
from ipapython import version
# pylint: enable=import-outside-toplevel
except ImportError:
return None
else:
version_info = []
for part in version.VERSION.split('.'):
# DEV versions look like:
# 4.4.90.201610191151GITd852c00
# 4.4.90.dev201701071308+git2e43db1
# 4.6.90.pre2
if part.startswith('dev') or part.startswith('pre') or \
'GIT' in part:
version_info.append(part)
else:
version_info.append(int(part))
return dict(
api_version=version.API_VERSION,
num_version=version.NUM_VERSION,
vendor_version=version.VENDOR_VERSION,
version=version.VERSION,
version_info=version_info
)
def main():
module = AnsibleModule(
argument_spec={},
supports_check_mode=True
)
# The module does not change anything, meaning that
# check mode is supported
facts = dict(
packages=dict(
ipalib=HAS_IPALIB,
ipaserver=HAS_IPASERVER,
),
configured=dict(
client=False,
server=False,
dns=False,
ca=False,
kra=False,
ntpd=False
)
)
if HAS_IPALIB:
if is_client_configured():
facts['configured']['client'] = True
facts['version'] = get_ipa_version()
for key, value in six.iteritems(get_ipa_conf()):
facts[key] = value
if HAS_IPASERVER:
if is_server_configured():
facts['configured']['server'] = True
facts['configured']['dns'] = is_dns_configured()
facts['configured']['ca'] = is_ca_configured()
facts['configured']['kra'] = is_kra_configured()
facts['configured']['ntpd'] = is_ntpd_configured()
module.exit_json(
changed=False,
ansible_facts=dict(ipa=facts)
)
if __name__ == '__main__':
main()
ansible-freeipa-v1.7.0/roles/ipaclient/library/ipaclient_get_otp.py 0000664 0000000 0000000 00000023660 14232747165 0025560 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Florence Blanc-Renaud
#
# Copyright (C) 2017 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_get_otp
short description: Manage IPA hosts
description:
Manage hosts in a IPA domain.
The operation needs to be authenticated with Kerberos either by providing
a password or a keytab corresponding to a principal allowed to perform
host operations.
options:
principal:
description:
User Principal allowed to promote replicas and join IPA realm
required: yes
ccache:
description: The local ccache
required: yes
fqdn:
description:
The fully-qualified hostname of the host to add/modify/remove
required: no
certificates:
description: A list of host certificates
required: yes
sshpubkey:
description: The SSH public key for the host
required: yes
ipaddress:
description: The IP address for the host
required: yes
random:
description: Generate a random password to be used in bulk enrollment
required: yes
state:
description: The desired host state
required: yes
author:
- "Florence Blanc-Renaud"
'''
EXAMPLES = '''
# Example from Ansible Playbooks
# Add a new host with a random OTP, authenticate using principal/password
- ipaclient_get_otp:
principal: admin
password: MySecretPassword
fqdn: ipaclient.ipa.domain.com
ipaddress: 192.168.100.23
random: True
register: result_ipaclient_get_otp
'''
RETURN = '''
host:
description: the host structure as returned from IPA API
returned: always
type: complex
contains:
dn:
description: the DN of the host entry
type: string
returned: always
fqdn:
description: the fully qualified host name
type: string
returned: always
has_keytab:
description: whether the host entry contains a keytab
type: bool
returned: always
has_password:
description: whether the host entry contains a password
type: bool
returned: always
managedby_host:
description: the list of hosts managing the host
type: list
returned: always
randompassword:
description: the OneTimePassword generated for this host
type: string
returned: changed
certificates:
description: the list of host certificates
type: list
returned: when present
sshpubkey:
description: the SSH public key for the host
type: string
returned: when present
ipaddress:
description: the IP address for the host
type: string
returned: when present
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils import six
from ipalib import api, errors
from ipaplatform.paths import paths
from ipapython.ipautil import run
if six.PY3:
unicode = str
def get_host_diff(ipa_host, module_host):
"""
Build a dict with the differences from two host dicts.
:param ipa_host: the host structure seen from IPA
:param module_host: the target host structure seen from the module params
:return: a dict representing the host attributes to apply
"""
non_updateable_keys = ['ip_address']
data = {}
for key in non_updateable_keys:
if key in module_host:
del module_host[key]
for key in module_host.keys():
ipa_value = ipa_host.get(key, None)
module_value = module_host.get(key, None)
if isinstance(ipa_value, list) and not isinstance(module_value, list):
module_value = [module_value]
if isinstance(ipa_value, list) and isinstance(module_value, list):
ipa_value = sorted(ipa_value)
module_value = sorted(module_value)
if ipa_value != module_value:
data[key] = unicode(module_value)
return data
def get_module_host(module):
"""
Create a structure representing the host information.
Reads the module parameters and builds the host structure as expected from
the module
:param module: the ansible module
:returns: a dict representing the host attributes
"""
data = {}
certificates = module.params.get('certificates')
if certificates:
data['usercertificate'] = certificates
sshpubkey = module.params.get('sshpubkey')
if sshpubkey:
data['ipasshpubkey'] = unicode(sshpubkey)
ipaddress = module.params.get('ipaddress')
if ipaddress:
data['ip_address'] = unicode(ipaddress)
random = module.params.get('random')
if random:
data['random'] = random
return data
def ensure_host_present(module, _api, ipahost):
"""
Ensure host exists in IPA and has the same attributes.
:param module: the ansible module
:param api: IPA api handle
:param ipahost: the host information present in IPA, can be none if the
host does not exist
"""
fqdn = unicode(module.params.get('fqdn'))
if ipahost:
# Host already present, need to compare the attributes
module_host = get_module_host(module)
diffs = get_host_diff(ipahost, module_host)
if not diffs:
# Same attributes, success
module.exit_json(changed=False, host=ipahost)
# Need to modify the host - only if not in check_mode
if module.check_mode:
module.exit_json(changed=True)
# If we want to create a random password, and the host
# already has Keytab: true, then we need first to run
# ipa host-disable in order to remove OTP and keytab
if module.params.get('random') and ipahost['has_keytab'] is True:
_api.Command.host_disable(fqdn)
result = _api.Command.host_mod(fqdn, **diffs)
# Save random password as it is not displayed by host-show
if module.params.get('random'):
randompassword = result['result']['randompassword']
result = _api.Command.host_show(fqdn)
if module.params.get('random'):
result['result']['randompassword'] = randompassword
module.exit_json(changed=True, host=result['result'])
if not ipahost:
# Need to add the user, only if not in check_mode
if module.check_mode:
module.exit_json(changed=True)
# Must add the user
module_host = get_module_host(module)
# force creation of host even if there is no DNS record
module_host["force"] = True
result = _api.Command.host_add(fqdn, **module_host)
# Save random password as it is not displayed by host-show
if module.params.get('random'):
randompassword = result['result']['randompassword']
result = _api.Command.host_show(fqdn)
if module.params.get('random'):
result['result']['randompassword'] = randompassword
module.exit_json(changed=True, host=result['result'])
def ensure_host_absent(module, _api, host):
"""
Ensure host does not exist in IPA.
:param module: the ansible module
:param api: the IPA API handle
:param host: the host information present in IPA, can be none if the
host does not exist
"""
if not host:
# Nothing to do, host already removed
module.exit_json(changed=False)
# Need to remove the host - only if not in check_mode
if module.check_mode:
module.exit_json(changed=True, host=host)
fqdn = unicode(module.params.get('fqdn'))
try:
_api.Command.host_del(fqdn)
except Exception as e:
module.fail_json(msg="Failed to remove host: %s" % e)
module.exit_json(changed=True)
def main():
module = AnsibleModule(
argument_spec=dict(
principal=dict(default='admin'),
ccache=dict(required=False, type='path'),
fqdn=dict(required=True),
certificates=dict(required=False, type='list'),
sshpubkey=dict(required=False),
ipaddress=dict(required=False),
random=dict(default=False, type='bool'),
state=dict(default='present', choices=['present', 'absent']),
),
supports_check_mode=True,
)
ccache = module.params.get('ccache')
fqdn = unicode(module.params.get('fqdn'))
state = module.params.get('state')
try:
os.environ['KRB5CCNAME'] = ccache
cfg = dict(
context='ansible_module',
confdir=paths.ETC_IPA,
in_server=False,
debug=False,
verbose=0,
)
api.bootstrap(**cfg)
api.finalize()
api.Backend.rpcclient.connect()
try:
result = api.Command.host_show(fqdn, all=True)
host = result['result']
except errors.NotFound:
host = None
if state in ['present', 'disabled']:
ensure_host_present(module, api, host)
elif state == 'absent':
ensure_host_absent(module, api, host)
except Exception as e:
module.fail_json(msg="ipaclient_get_otp module failed : %s" % str(e))
finally:
run([paths.KDESTROY], raiseonerr=False, env=os.environ)
module.exit_json(changed=False, host=host)
if __name__ == '__main__':
main()
ansible-freeipa-v1.7.0/roles/ipaclient/library/ipaclient_ipa_conf.py 0000664 0000000 0000000 00000005611 14232747165 0025671 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2018 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
required: no
servers:
description: Fully qualified name of IPA servers to enroll to
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: no
basedn:
description: The basedn of the IPA server (of the form dc=example,dc=com)
required: no
author:
- Thomas 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, paths, sysrestore, configure_ipa_conf
)
def main():
module = AnsibleModule(
argument_spec=dict(
domain=dict(required=True, default=None),
servers=dict(required=True, type='list', default=None),
realm=dict(required=True, default=None),
hostname=dict(required=True, default=None),
basedn=dict(required=True),
),
supports_check_mode=True,
)
module._ansible_debug = True
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-v1.7.0/roles/ipaclient/library/ipaclient_join.py 0000664 0000000 0000000 00000027213 14232747165 0025054 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: no
kdc:
description: The name or address of the host running the KDC
required: no
basedn:
description: The basedn of the IPA server (of the form dc=example,dc=com)
required: no
principal:
description:
User Principal allowed to promote replicas and join IPA realm
required: yes
password:
description: Admin user kerberos password
required: yes
keytab:
description: Path to backed up keytab from previous enrollment
required: yes
admin_keytab:
description: The path to a local admin keytab
required: yes
ca_cert_file:
description:
A CA certificate to use. Do not acquire the IPA CA certificate via
automated means
required: yes
force_join:
description: Force client enrollment even if already enrolled
required: yes
kinit_attempts:
description: Repeat the request for host Kerberos ticket X times
required: yes
debug:
description: Turn on extra debugging
required: yes
author:
- Thomas 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"]
domain: example.com
realm: EXAMPLE.COM
kdc: server1.example.com
basedn: dc=example,dc=com
hostname: client1.example.com
principal: admin
password: MySecretPassword
force_join: yes
kinit_attempts: 5
# Join IPA to get the keytab using ipadiscovery return values
- name: Join IPA
ipaclient_join:
servers: "{{ ipadiscovery.servers }}"
domain: "{{ ipadiscovery.domain }}"
realm: "{{ ipadiscovery.realm }}"
kdc: "{{ ipadiscovery.kdc }}"
basedn: "{{ ipadiscovery.basedn }}"
hostname: "{{ ipadiscovery.hostname }}"
principal: admin
password: MySecretPassword
'''
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,
SECURE_PATH, sysrestore, paths, options, configure_krb5_conf,
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'),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=True),
kdc=dict(required=True),
basedn=dict(required=True),
principal=dict(required=False),
password=dict(required=False, no_log=True),
keytab=dict(required=False),
admin_keytab=dict(required=False),
ca_cert_file=dict(required=False),
force_join=dict(required=False, type='bool'),
kinit_attempts=dict(required=False, type='int', default=5),
debug=dict(required=False, type='bool'),
),
supports_check_mode=True,
)
module._ansible_debug = True
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')
kdc = module.params.get('kdc')
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')
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")
client_domain = hostname[hostname.find(".") + 1:]
nolog = tuple()
env = {'PATH': SECURE_PATH}
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
host_principal = 'host/%s@%s' % (hostname, realm)
sssd = True
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:
(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)
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: {}".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: {}".format(e))
else:
module.fail_json(
msg="Keytab file could not be found: {}".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)
del os.environ['KRB5_CONFIG']
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)
env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
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:
try:
os.remove(krb_name)
except OSError:
module.fail_json(msg="Could not remove %s" % krb_name)
if ccache_dir is not None:
try:
os.rmdir(ccache_dir)
except OSError:
pass
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=changed,
already_joined=already_joined)
if __name__ == '__main__':
main()
ansible-freeipa-v1.7.0/roles/ipaclient/library/ipaclient_set_hostname.py 0000664 0000000 0000000 00000004161 14232747165 0026603 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2018 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
required: no
author:
- Thomas 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, sysrestore, paths, tasks
)
def main():
module = AnsibleModule(
argument_spec=dict(
hostname=dict(required=True),
),
supports_check_mode=True,
)
module._ansible_debug = True
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-v1.7.0/roles/ipaclient/library/ipaclient_setup_automount.py 0000664 0000000 0000000 00000005101 14232747165 0027360 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
sssd:
description: The installer sssd setting
required: yes
automount_location:
description: The automount location
required: yes
author:
- Thomas 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, options, configure_automount
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list'),
sssd=dict(required=False, type='bool', default='yes'),
automount_location=dict(required=False, default=None),
),
supports_check_mode=True,
)
# os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
module._ansible_debug = True
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
if options.automount_location:
configure_automount(options)
module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-v1.7.0/roles/ipaclient/library/ipaclient_setup_firefox.py 0000664 0000000 0000000 00000004551 14232747165 0026777 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: yes
firefox_dir:
description:
Specify directory where Firefox is installed (for example
'/usr/lib/firefox')
required: no
author:
- Thomas 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, sysrestore, paths, options, configure_firefox
)
def main():
module = AnsibleModule(
argument_spec=dict(
domain=dict(required=True),
firefox_dir=dict(required=False),
),
supports_check_mode=True,
)
module._ansible_debug = True
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-v1.7.0/roles/ipaclient/library/ipaclient_setup_krb5.py 0000664 0000000 0000000 00000011066 14232747165 0026177 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2018 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
required: yes
servers:
description: Fully qualified name of IPA servers to enroll to
required: yes
realm:
description: Kerberos realm name of the IPA deployment
required: yes
hostname:
description: Fully qualified name of this host
required: yes
kdc:
description: The name or address of the host running the KDC
required: yes
dnsok:
description: The installer dnsok setting
required: yes
client_domain:
description: Primary DNS domain of the IPA deployment
required: yes
sssd:
description: The installer sssd setting
required: yes
force:
description: Installer force parameter
required: yes
author:
- Thomas 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, sysrestore, paths, configure_krb5_conf, logger
)
def main():
module = AnsibleModule(
argument_spec=dict(
domain=dict(required=False, default=None),
servers=dict(required=False, type='list', default=None),
realm=dict(required=False, default=None),
hostname=dict(required=False, default=None),
kdc=dict(required=False, default=None),
dnsok=dict(required=False, type='bool', default=False),
client_domain=dict(required=False, 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=True,
)
module._ansible_debug = True
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-v1.7.0/roles/ipaclient/library/ipaclient_setup_nis.py 0000664 0000000 0000000 00000005013 14232747165 0026120 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
nisdomain:
description: The NIS domain name
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
- name: Setup NIS for IPA client
ipaclient_setup_nis:
domain: example.com
'''
RETURN = '''
'''
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging, options, sysrestore, paths, configure_nisdomain
)
def main():
module = AnsibleModule(
argument_spec=dict(
domain=dict(required=True),
nisdomain=dict(required=False),
),
supports_check_mode=True,
)
module._ansible_debug = True
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 = inspect.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-v1.7.0/roles/ipaclient/library/ipaclient_setup_nss.py 0000664 0000000 0000000 00000045631 14232747165 0026144 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: no
basedn:
description: The basedn of the IPA server (of the form dc=example,dc=com)
required: no
principal:
description:
User Principal allowed to promote replicas and join IPA realm
required: yes
subject_base:
description: |
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
ca_enabled:
description: Whether the Certificate Authority is enabled or not
required: no
mkhomedir:
description: Create home directories for users on their first login
required: yes
on_master:
description: Whether the configuration is done on the master or not
required: yes
dnsok:
description: The installer dnsok setting
required: yes
enable_dns_updates:
description: |
Configures the machine to attempt dns updates when the ip address
changes
required: yes
all_ip_addresses:
description: |
All routable IP addresses configured on any interface will be added
to DNS
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: yes
request_cert:
description: Request certificate for the machine
required: yes
preserve_sssd:
description: Preserve old SSSD configuration if possible
required: yes
no_ssh:
description: Do not configure OpenSSH client
required: yes
no_sshd:
description: Do not configure OpenSSH server
required: yes
no_sudo:
description: Do not configure SSSD as data source for sudo
required: yes
fixed_primary:
description: Configure sssd to use fixed server as primary IPA server
required: yes
permit:
description: Disable access rules by default, permit all access
required: yes
no_krb5_offline_passwords:
description:
Configure SSSD not to store user password when the server is offline
required: yes
no_dns_sshfp:
description: Do not automatically create DNS SSHFP records
required: yes
nosssd_files:
description: >
The dist of nss_ldap or nss-pam-ldapd files if sssd is disabled
required: yes
type: dict
author:
- Thomas 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
'''
RETURN = '''
'''
import os
import time
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging,
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, configure_certmonger, services,
update_ssh_keys, save_state, configure_ldap_conf, configure_nslcd_conf,
configure_openldap_conf, hardcode_ldap_server
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list'),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=True),
basedn=dict(required=True),
principal=dict(required=False),
subject_base=dict(required=True),
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', 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'),
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'),
),
supports_check_mode=True,
)
module._ansible_debug = True
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.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')
# 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
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)
configure_certmonger(fstore, subject_base, cli_realm, hostname,
options, ca_enabled)
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 = inspect.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 = inspect.getargspec(tasks.modify_nsswitch_pam_stack)
if "sudo" in argspec.args:
tasks.modify_nsswitch_pam_stack(
sssd=options.sssd,
mkhomedir=options.mkhomedir,
statestore=statestore,
sudo=options.conf_sudo
)
else:
tasks.modify_nsswitch_pam_stack(
sssd=options.sssd,
mkhomedir=options.mkhomedir,
statestore=statestore
)
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:
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-v1.7.0/roles/ipaclient/library/ipaclient_setup_ntp.py 0000664 0000000 0000000 00000013437 14232747165 0026141 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: yes
ntp_pool:
description: ntp server pool to use
required: yes
no_ntp:
description: Do not configure ntp
required: yes
on_master:
description: Whether the configuration is done on the master or not
required: yes
servers:
description: Fully qualified name of IPA servers to enroll to
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import (
setup_logging,
options, sysrestore, paths, sync_time, logger, ipadiscovery,
timeconf
)
def main():
module = AnsibleModule(
argument_spec=dict(
# basic
ntp_servers=dict(required=False, type='list', default=None),
ntp_pool=dict(required=False, 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', default=None),
domain=dict(required=False, default=None),
),
supports_check_mode=True,
)
# module._ansible_debug = True
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 = inspect.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-v1.7.0/roles/ipaclient/library/ipaclient_setup_ssh.py 0000664 0000000 0000000 00000006463 14232747165 0026136 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
no_ssh:
description: Do not configure OpenSSH client
required: yes
ssh_trust_dns:
description: Configure OpenSSH client to trust DNS SSHFP records
required: yes
no_sshd:
description: Do not configure OpenSSH server
required: yes
sssd:
description: The installer sssd setting
required: yes
author:
- Thomas 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,
options, sysrestore, paths, configure_ssh_config, configure_sshd_config
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list'),
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=True,
)
module._ansible_debug = True
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-v1.7.0/roles/ipaclient/library/ipaclient_setup_sssd.py 0000664 0000000 0000000 00000012662 14232747165 0026313 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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_ssd
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
required: no
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: no
on_master:
description: Whether the configuration is done on the master or not
required: yes
no_ssh:
description: Do not configure OpenSSH client
required: yes
no_sshd:
description: Do not configure OpenSSH server
required: yes
no_sudo:
description: Do not configure SSSD as data source for sudo
required: yes
all_ip_addresses:
description:
All routable IP addresses configured on any interface will be added
to DNS
required: yes
fixed_primary:
description: Configure sssd to use fixed server as primary IPA server
required: yes
permit:
description: Disable access rules by default, permit all access
required: yes
enable_dns_updates:
description:
Configures the machine to attempt dns updates when the ip address
changes
required: yes
preserve_sssd:
description: Preserve old SSSD configuration if possible
required: yes
no_krb5_offline_passwords:
description:
Configure SSSD not to store user password when the server is offline
required: yes
author:
- Thomas 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, options, sysrestore, paths, configure_sssd_conf, logger
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list'),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=True),
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=True,
)
# ansible_log = AnsibleModuleLog(module, logger)
# options.set_logger(ansible_log)
module._ansible_debug = True
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-v1.7.0/roles/ipaclient/library/ipaclient_test.py 0000664 0000000 0000000 00000103770 14232747165 0025077 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: yes
servers:
description: Fully qualified name of IPA servers to enroll to
required: yes
realm:
description: Kerberos realm name of the IPA deployment
required: yes
hostname:
description: Fully qualified name of this host
required: yes
ntp_servers:
description: ntp servers to use
required: yes
ntp_pool:
description: ntp server pool to use
required: yes
no_ntp:
description: Do not configure ntp
required: yes
force_ntpd:
description:
Stop and disable any time&date synchronization services besides ntpd
Deprecated since 4.7
required: yes
nisdomain:
description: The NIS domain name
required: yes
no_nisdomain:
description: Do not configure NIS domain name
required: yes
kinit_attempts:
description: Repeat the request for host Kerberos ticket X times
required: yes
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
required: yes
configure_firefox:
description: Configure Firefox to use IPA domain credentials
required: yes
firefox_dir:
description:
Specify directory where Firefox is installed (for example
'/usr/lib/firefox')
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: yes
all_ip_addresses:
description:
All routable IP addresses configured on any interface will be added
to DNS
required: yes
on_master:
description: Whether the configuration is done on the master or not
required: yes
enable_dns_updates:
description:
Configures the machine to attempt dns updates when the ip address
changes
required: yes
author:
- Thomas 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
sample: ["server1.example.com","server2.example.com"]
domain:
description: The DNS domain of the detected or passed in IPA deployment.
returned: always
type: string
sample: example.com
realm:
description: The Kerberos realm of the detected or passed in IPA deployment.
returned: always
type: string
sample: EXAMPLE.COM
kdc:
description: The detected KDC server name.
returned: always
type: string
sample: server1.example.com
basedn:
description: The basedn of the detected IPA server.
returned: always
type: string
sample: dc=example,dc=com
hostname:
description: The detected or passed in FQDN hostname of the client.
returned: always
type: string
sample: client1.example.com
client_domain:
description: The domain name of the client.
returned: always
type: string
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
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
type: list
'''
import os
import socket
import inspect
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,
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
)
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, default=None),
servers=dict(required=False, type='list', default=None),
realm=dict(required=False, default=None),
hostname=dict(required=False, default=None),
ntp_servers=dict(required=False, type='list', default=None),
ntp_pool=dict(required=False, default=None),
no_ntp=dict(required=False, type='bool', default=False),
force_ntpd=dict(required=False, type='bool', default=False),
nisdomain=dict(required=False, 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', default=None),
configure_firefox=dict(required=False, type='bool', default=False),
firefox_dir=dict(required=False),
ip_addresses=dict(required=False, type='list', 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=True,
)
# module._ansible_debug = True
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 = inspect.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 {!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
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)
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 '{}', must be lower-case.".format(hostname),
rval=CLIENT_INSTALL_ERROR
)
if hostname in ('localhost', 'localhost.localdomain'):
raise ScriptError(
"Invalid hostname, '{}' 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: {}'.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(
"{} 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.info()
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)
if __name__ == '__main__':
main()
ansible-freeipa-v1.7.0/roles/ipaclient/library/ipaclient_test_keytab.py 0000664 0000000 0000000 00000015030 14232747165 0026425 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: no
kdc:
description: The name or address of the host running the KDC
required: no
kinit_attempts:
description: Repeat the request for host Kerberos ticket X times
required: yes
author:
- Thomas 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
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,
SECURE_PATH, paths, kinit_keytab, run, GSSError, configure_krb5_conf
)
def main():
module = AnsibleModule(
argument_spec=dict(
servers=dict(required=True, type='list'),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=True),
kdc=dict(required=True),
kinit_attempts=dict(required=False, type='int', default=5),
),
supports_check_mode=True,
)
module._ansible_debug = True
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 krb5 keytab with system krb5 configuraiton
try:
kinit_keytab(host_principal, paths.KRB5_KEYTAB,
paths.IPA_DNS_CCACHE,
config=paths.KRB5_CONF,
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
# 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)
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-v1.7.0/roles/ipaclient/meta/ 0000775 0000000 0000000 00000000000 14232747165 0020770 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaclient/meta/main.yml 0000664 0000000 0000000 00000000547 14232747165 0022445 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.8
platforms:
- name: Fedora
versions:
- all
- name: EL
versions:
- 7
- 8
galaxy_tags:
- identity
- ipa
- freeipa
ansible-freeipa-v1.7.0/roles/ipaclient/module_utils/ 0000775 0000000 0000000 00000000000 14232747165 0022547 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaclient/module_utils/ansible_ipa_client.py 0000664 0000000 0000000 00000031275 14232747165 0026735 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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"]
import sys
# HACK: workaround for Ansible 2.9
# https://github.com/ansible/ansible/issues/68361
if 'ansible.executor' in sys.modules:
for attr in __all__:
setattr(sys.modules[__name__], attr, None)
else:
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 inspect
import gssapi
import logging
from ipapython import version
try:
from ipaclient.install import ipadiscovery
except ImportError:
from ipaclient import ipadiscovery
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 = inspect.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 = \
inspect.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
logger = logging.getLogger("ipa-client-install")
root_logger = logger
else:
# IPA version < 4.4
raise Exception("freeipa version '%s' is too old" % VERSION)
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
ansible-freeipa-v1.7.0/roles/ipaclient/tasks/ 0000775 0000000 0000000 00000000000 14232747165 0021167 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaclient/tasks/install.yml 0000664 0000000 0000000 00000040303 14232747165 0023360 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipaclient
- name: Install - Ensure that IPA client packages are installed
package:
name: "{{ ipaclient_packages }}"
state: present
when: ipaclient_install_packages | bool
- name: Install - Set ipaclient_servers
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
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 principal or keytab is set
fail: msg="ipaadmin_principal and ipaadmin_keytab cannot be used together"
when: ipaadmin_keytab is defined and ipaadmin_principal is defined
- name: Install - Set default principal if no keytab is given
set_fact:
ipaadmin_principal: admin
when: ipaadmin_principal is undefined and ipaclient_keytab is undefined
- 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
- block:
- name: Install - Cleanup leftover ccache
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
set_fact:
ipaclient_use_otp: "yes"
when: ipaclient_otp is defined
- name: Install - Disable One-Time Password for on_master
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
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.
- block:
- name: Install - Keytab or password is required for getting otp
fail: msg="Keytab or password is required for getting otp"
when: ipaadmin_keytab is undefined and ipaadmin_password is undefined
- name: Install - Get One-Time Password for client enrollment
no_log: yes
ipaclient_get_otp:
state: present
principal: "{{ ipaadmin_principal | default(omit) }}"
password: "{{ ipaadmin_password | default(omit) }}"
keytab: "{{ ipaadmin_keytab | default(omit) }}"
fqdn: "{{ result_ipaclient_test.hostname }}"
lifetime: "{{ ipaclient_lifetime | default(omit) }}"
random: True
register: result_ipaclient_get_otp
# If the host is already enrolled, this command will exit on error
# The error can be ignored
failed_when: result_ipaclient_get_otp is failed and
"Password cannot be set on enrolled host" not
in result_ipaclient_get_otp.msg
delegate_to: "{{ result_ipaclient_test.servers[0] }}"
ignore_errors: yes
- name: Install - Report error for OTP generation
debug:
msg: "{{ result_ipaclient_get_otp.msg }}"
when: result_ipaclient_get_otp is failed
failed_when: yes
- name: Install - Store the previously obtained OTP
no_log: yes
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 }}"
when: ipaclient_use_otp | bool and ipaclient_otp is not defined
- name: Store predefined OTP in admin_password
no_log: yes
set_fact:
ipaadmin_orig_password: "{{ ipaadmin_password | default(omit) }}"
ipaadmin_password: "{{ ipaclient_otp }}"
when: ipaclient_otp is defined
- 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
fail: msg="Principal and 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
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
when: not ipaclient_on_master | bool
- name: Install - Purge {{ result_ipaclient_test.realm }} from host keytab
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 - Join IPA
ipaclient_join:
servers: "{{ result_ipaclient_test.servers }}"
domain: "{{ result_ipaclient_test.domain }}"
realm: "{{ result_ipaclient_test.realm }}"
kdc: "{{ result_ipaclient_test.kdc }}"
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) }}"
register: result_ipaclient_join
when: not ipaclient_on_master | bool and
(not result_ipaclient_test_keytab.krb5_keytab_ok or
ipaclient_force_join)
- block:
- name: krb5 configuration not correct
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
fail:
msg: "The IPA test failed, please enable allow_repair to fix this."
when: not result_ipaclient_test_keytab.ping_test_ok
- name: ca.crt file is missing
fail:
msg: >
The ca.crt file is missing, please enable allow_repair to fix this.
when: not result_ipaclient_test_keytab.ca_crt_exists
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: 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 - 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 - 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
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 }}"
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 }}"
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 }}"
- 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: "{{ ipaautomount_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
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)))
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)
always:
- name: Install - Restore original admin password if overwritten by OTP
no_log: yes
set_fact:
ipaadmin_password: "{{ ipaadmin_orig_password }}"
when: ipaclient_use_otp | bool and ipaadmin_orig_password is defined
- name: Cleanup leftover ccache
file:
path: "/etc/ipa/.dns_ccache"
state: absent
ansible-freeipa-v1.7.0/roles/ipaclient/tasks/main.yml 0000664 0000000 0000000 00000002313 14232747165 0022635 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipaclient
- name: Import variables specific to distribution
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
include_tasks: install.yml
when: state|default('present') == 'present'
- name: Uninstall IPA client
include_tasks: uninstall.yml
when: state|default('present') == 'absent'
ansible-freeipa-v1.7.0/roles/ipaclient/tasks/uninstall.yml 0000664 0000000 0000000 00000000663 14232747165 0023730 0 ustar 00root root 0000000 0000000 ---
# tasks to uninstall IPA client
- name: Uninstall - Uninstall IPA client
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: Remove IPA client package
# package:
# name: "{{ ipaclient_packages }}"
# state: absent
ansible-freeipa-v1.7.0/roles/ipaclient/vars/ 0000775 0000000 0000000 00000000000 14232747165 0021015 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaclient/vars/Debian-10.yml 0000664 0000000 0000000 00000000432 14232747165 0023137 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-v1.7.0/roles/ipaclient/vars/Debian.yml 0000664 0000000 0000000 00000000135 14232747165 0022721 0 ustar 00root root 0000000 0000000 # defaults file for ipaclient
# vars/Debian.yml
---
ipaclient_packages: [ "freeipa-client" ]
ansible-freeipa-v1.7.0/roles/ipaclient/vars/Fedora-25.yml 0000664 0000000 0000000 00000000241 14232747165 0023161 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-v1.7.0/roles/ipaclient/vars/Fedora-26.yml 0000664 0000000 0000000 00000000241 14232747165 0023162 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-v1.7.0/roles/ipaclient/vars/RedHat-7.3.yml 0000664 0000000 0000000 00000000264 14232747165 0023216 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-v1.7.0/roles/ipaclient/vars/RedHat-7.yml 0000664 0000000 0000000 00000000234 14232747165 0023052 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-v1.7.0/roles/ipaclient/vars/RedHat-8.yml 0000664 0000000 0000000 00000000140 14232747165 0023047 0 ustar 00root root 0000000 0000000 # defaults file for ipaclient
# vars/RedHat-8.yml
---
ipaclient_packages: [ "@idm:DL1/client" ]
ansible-freeipa-v1.7.0/roles/ipaclient/vars/Ubuntu-18.04.yml 0000664 0000000 0000000 00000000451 14232747165 0023472 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-v1.7.0/roles/ipaclient/vars/default.yml 0000664 0000000 0000000 00000000240 14232747165 0023160 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-v1.7.0/roles/ipareplica/ 0000775 0000000 0000000 00000000000 14232747165 0020203 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipareplica/README.md 0000664 0000000 0000000 00000025553 14232747165 0021474 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+
* Fedora 26+
* Ubuntu
Requirements
------------
**Controller**
* Ansible version: 2.8+
**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
```
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_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
Authors
=======
Thomas Woerner
ansible-freeipa-v1.7.0/roles/ipareplica/defaults/ 0000775 0000000 0000000 00000000000 14232747165 0022012 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipareplica/defaults/main.yml 0000664 0000000 0000000 00000002053 14232747165 0023461 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-v1.7.0/roles/ipareplica/library/ 0000775 0000000 0000000 00000000000 14232747165 0021647 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipareplica/library/ipareplica_add_to_ipaservers.py 0000664 0000000 0000000 00000007725 14232747165 0030122 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
ccache:
description: The local ccache
required: no
installer_ccache:
description: The installer ccache setting
required: no
_top_dir:
description: The installer _top_dir setting
required: no
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
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),
ccache=dict(required=True),
installer_ccache=dict(required=True),
_top_dir=dict(required=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_create_ipa_conf.py 0000664 0000000 0000000 00000023332 14232747165 0027516 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
password:
description: Admin user kerberos password
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
realm:
description: Kerberos realm name of the IPA deployment
required: yes
hostname:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
force_join:
description: Force client enrollment even if already enrolled
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
server:
description: Fully qualified name of IPA server to enroll to
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
config_ca_host_name:
description: The config ca_host_name setting
required: no
ccache:
description: The local ccache
required: no
installer_ccache:
description: The installer ccache setting
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
_add_to_ipaservers:
description: The installer _add_to_ipaservers setting
required: no
_ca_subject:
description: The installer _ca_subject setting
required: no
_subject_base:
description: The installer _subject_base setting
required: no
master:
description: Master host name
required: yes
dirman_password:
description: Directory Manager (master) password
required: no
author:
- Thomas 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,
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, no_log=True),
password=dict(required=False, no_log=True),
ip_addresses=dict(required=False, type='list', default=[]),
domain=dict(required=False),
realm=dict(required=False),
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', 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', default=[]),
# client
force_join=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True),
# additional
server=dict(required=True),
config_master_host_name=dict(required=True),
config_ca_host_name=dict(required=True),
ccache=dict(required=True),
installer_ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_top_dir=dict(required=True),
_add_to_ipaservers=dict(required=True, type='bool'),
_ca_subject=dict(required=True),
_subject_base=dict(required=True),
master=dict(required=False, default=None),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_custodia_import_dm_password.py 0000664 0000000 0000000 00000015647 14232747165 0032236 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
no_ui_redirect:
description: Do not automatically redirect to the Web UI
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
ccache:
description: The local ccache
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description: The installer _ca_file setting
required: yes
_kra_enabled:
description: The installer _kra_enabled setting
required: yes
_kra_host_name:
description: The installer _kra_host_name setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
config_setup_ca:
description: The config setup_ca setting
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
config_ca_host_name:
description: The config ca_host_name setting
required: no
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, setup_logging, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_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),
# additional
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_kra_enabled=dict(required=False, type='bool'),
_kra_host_name=dict(required=False),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
config_ca_host_name=dict(required=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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 = inspect.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-v1.7.0/roles/ipareplica/library/ipareplica_ds_apply_updates.py 0000664 0000000 0000000 00000016506 14232747165 0027762 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
no_ui_redirect:
description: Do not automatically redirect to the Web UI
required: yes
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
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
ccache:
description: The local ccache
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description: The installer _ca_file setting
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
ds_ca_subject:
description: The ds.ca_subject setting
required: no
author:
- Thomas 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,
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),
# certificate system
subject_base=dict(required=True),
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_dirsrv_pkcs12_info=dict(required=False, type='list'),
_pkinit_pkcs12_info=dict(required=False, type='list'),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
ds_ca_subject=dict(required=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_ds_enable_ssl.py 0000664 0000000 0000000 00000015041 14232747165 0027210 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
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
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
ccache:
description: The local ccache
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description: The installer _ca_file setting
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
ds_ca_subject:
description: The ds.ca_subject setting
required: no
author:
- Thomas 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,
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),
# certificate system
subject_base=dict(required=True),
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_dirsrv_pkcs12_info=dict(required=False, type='list'),
_pkinit_pkcs12_info=dict(required=False, type='list'),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
ds_ca_subject=dict(required=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_enable_ipa.py 0000664 0000000 0000000 00000012524 14232747165 0026475 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
hidden_replica:
description: Install a hidden replica
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
ccache:
description: The local ccache
required: no
_top_dir:
description: The installer _top_dir setting
required: no
setup_ca:
description: Configure a dogtag CA
required: no
setup_kra:
description: Configure a dogtag KRA
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
author:
- Thomas 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,
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),
hidden_replica=dict(required=False, type='bool', default=False),
# server
# certificate system
subject_base=dict(required=True),
# additional
ccache=dict(required=True),
_top_dir=dict(required=True),
setup_ca=dict(required=True, type='bool'),
setup_kra=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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 ({}).
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-v1.7.0/roles/ipareplica/library/ipareplica_install_ca_certs.py 0000664 0000000 0000000 00000025216 14232747165 0027731 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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_cert
short description: Install CA certs
description:
Install CA certs
options:
dm_password:
description: Directory Manager password
required: yes
password:
description: Admin user kerberos password
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
realm:
description: Kerberos realm name of the IPA deployment
required: yes
hostname:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
force_join:
description: Force client enrollment even if already enrolled
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
server:
description: Fully qualified name of IPA server to enroll to
required: no
ccache:
description: The local ccache
required: no
installer_ccache:
description: The installer ccache setting
required: no
_top_dir:
description: The installer _top_dir setting
required: no
_add_to_ipaservers:
description: The installer _add_to_ipaservers setting
required: no
_ca_subject:
description: The installer _ca_subject setting
required: no
_subject_base:
description: The installer _subject_base setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
config_setup_ca:
description: The config setup_ca setting
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
config_ca_host_name:
description: The config ca_host_name setting
required: no
config_ips:
description: The config ips setting
required: yes
author:
- Thomas 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,
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, no_log=True),
password=dict(required=False, no_log=True),
ip_addresses=dict(required=False, type='list', default=[]),
domain=dict(required=False),
realm=dict(required=False),
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', 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', default=[]),
# client
force_join=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True),
# additional
server=dict(required=True),
ccache=dict(required=True),
installer_ccache=dict(required=True),
_top_dir=dict(required=True),
_add_to_ipaservers=dict(required=True, type='bool'),
_ca_subject=dict(required=True),
_subject_base=dict(required=True),
dirman_password=dict(required=True, no_log=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
config_ca_host_name=dict(required=True),
config_ips=dict(required=False, type='list', default=[]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_krb_enable_ssl.py 0000664 0000000 0000000 00000013234 14232747165 0027362 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
ccache:
description: The local ccache
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description: The installer _ca_file setting
required: yes
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
author:
- Thomas 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, 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),
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_pkinit_pkcs12_info=dict(required=False, type='list'),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_master_password.py 0000664 0000000 0000000 00000004145 14232747165 0027633 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-server-install code
#
# Copyright (C) 2017 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)
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
password:
description: The master password
returned: always
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
setup_logging, ipa_generate_password
)
def main():
module = AnsibleModule(
argument_spec=dict(
# basic
master_password=dict(required=False, no_log=True),
),
supports_check_mode=True,
)
module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_prepare.py 0000664 0000000 0000000 00000100656 14232747165 0026060 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
password:
description: Admin user kerberos password
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
realm:
description: Kerberos realm name of the IPA deployment
required: yes
hostname:
description: Fully qualified name of this host
required: yes
principal:
description:
User Principal allowed to promote replicas and join IPA realm
required: no
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
dirsrv_cert_name:
description: Name of the Directory Server SSL certificate to install
required: yes
dirsrv_pin:
description: The password to unlock the Directory Server private key
required: yes
http_cert_files:
description:
File containing the Apache Server SSL certificate and private key
required: yes
http_cert_name:
description: Name of the Apache Server SSL certificate to install
required: yes
http_pin:
description: The password to unlock the Apache Server private key
required: yes
pkinit_cert_files:
description:
File containing the Kerberos KDC SSL certificate and private key
required: yes
pkinit_cert_name:
description: Name of the Kerberos KDC SSL certificate to install
required: yes
pkinit_pin:
description: The password to unlock the Kerberos KDC private key
required: yes
keytab:
description: Path to backed up keytab from previous enrollment
required: yes
mkhomedir:
description: Create home directories for users on their first login
required: yes
force_join:
description: Force client enrollment even if already enrolled
required: yes
no_ntp:
description: Do not configure ntp
required: yes
ssh_trust_dns:
description: Configure OpenSSH client to trust DNS SSHFP records
required: yes
no_ssh:
description: Do not configure OpenSSH client
required: yes
no_sshd:
description: Do not configure OpenSSH server
required: yes
no_dns_sshfp:
description: Do not automatically create DNS SSHFP records
required: yes
allow_zone_overlap:
description: Create DNS zone even if it already exists
required: yes
reverse_zones:
description: The reverse DNS zones to use
required: yes
no_reverse:
description: Do not create new reverse DNS zone
required: yes
auto_reverse:
description: Create necessary reverse zones
required: yes
forwarders:
description: Add DNS forwarders
required: yes
no_forwarders:
description: Do not add any DNS forwarders, use root servers instead
required: yes
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
required: yes
forward_policy:
description: DNS forwarding policy for global forwarders
required: yes
no_dnssec_validation:
description: Disable DNSSEC validation
required: yes
enable_compat:
description: Enable support for trusted domains for old clients
required: yes
netbios_name:
description: NetBIOS name of the IPA domain
required: yes
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
required: yes
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
required: yes
server:
description: Fully qualified name of IPA server to enroll to
required: no
skip_conncheck:
description: Skip connection check to remote master
required: yes
author:
- Thomas 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 (
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, no_log=True),
password=dict(required=False, no_log=True),
ip_addresses=dict(required=False, type='list', default=[]),
domain=dict(required=False),
realm=dict(required=False),
hostname=dict(required=False),
principal=dict(required=True),
ca_cert_files=dict(required=False, type='list', 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', default=[]),
dirsrv_cert_name=dict(required=False),
dirsrv_pin=dict(required=False),
http_cert_files=dict(required=False, type='list', default=[]),
http_cert_name=dict(required=False),
http_pin=dict(required=False),
pkinit_cert_files=dict(required=False, type='list', default=[]),
pkinit_cert_name=dict(required=False),
pkinit_pin=dict(required=False),
# client
keytab=dict(required=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', 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', default=[]),
no_forwarders=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
forward_policy=dict(default=None, choices=['first', 'only']),
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),
rid_base=dict(required=False, type='int', default=1000),
secondary_rid_base=dict(required=False, type='int',
default=100000000),
# additional
server=dict(required=True),
skip_conncheck=dict(required=False, type='bool'),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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')
# 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://{}/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://{}/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:
del os.environ['KRB5CCNAME']
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:
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:
del os.environ['KRB5CCNAME']
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,
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-v1.7.0/roles/ipareplica/library/ipareplica_promote_openldap_conf.py 0000664 0000000 0000000 00000010241 14232747165 0030764 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
ccache:
description: The local ccache
required: no
_top_dir:
description: The installer _top_dir setting
required: no
config_setup_ca:
description: The config setup_ca setting
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
author:
- Thomas 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,
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),
# additional
ccache=dict(required=True),
_top_dir=dict(required=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_promote_sssd.py 0000664 0000000 0000000 00000010123 14232747165 0027130 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
ccache:
description: The local ccache
required: no
_top_dir:
description: The installer _top_dir setting
required: no
config_setup_ca:
description: The config setup_ca setting
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
author:
- Thomas 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,
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),
# additional
ccache=dict(required=True),
_top_dir=dict(required=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_restart_kdc.py 0000664 0000000 0000000 00000012157 14232747165 0026725 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
no_ui_redirect:
description: Do not automatically redirect to the Web UI
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
ccache:
description: The local ccache
required: no
_ca_file:
description: The installer _ca_file setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
author:
- Thomas 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, 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),
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_ca_file=dict(required=False),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_setup_adtrust.py 0000664 0000000 0000000 00000012571 14232747165 0027326 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
enable_compat:
description: Enable support for trusted domains for old clients
required: yes
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
required: yes
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
required: yes
adtrust_netbios_name:
description: The adtrust netbios_name setting
required: no
adtrust_reset_netbios_name:
description: The adtrust reset_netbios_name setting
required: no
ccache:
description: The local ccache
required: no
_top_dir:
description: The installer _top_dir setting
required: no
setup_ca:
description: Configure a dogtag CA
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
author:
- Thomas 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
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# server
setup_kra=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True),
# 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),
adtrust_reset_netbios_name=dict(required=True, type='bool'),
# additional
ccache=dict(required=True),
_top_dir=dict(required=True),
setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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')
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-v1.7.0/roles/ipareplica/library/ipareplica_setup_ca.py 0000664 0000000 0000000 00000020743 14232747165 0026223 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
ccache:
description: The local ccache
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description: The installer _ca_file setting
required: yes
_kra_enabled:
description: The installer _kra_enabled setting
required: yes
_kra_host_name:
description: The installer _kra_host_name setting
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
_ca_subject:
description: The installer _ca_subject setting
required: no
_subject_base:
description: The installer _subject_base setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
config_setup_ca:
description: The config setup_ca setting
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
config_ca_host_name:
description: The config ca_host_name setting
required: no
config_ips:
description: The config ips setting
required: yes
author:
- Thomas 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,
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),
# 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),
# additional
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_kra_enabled=dict(required=False, type='bool'),
_kra_host_name=dict(required=False),
_dirsrv_pkcs12_info=dict(required=False, type='list'),
_pkinit_pkcs12_info=dict(required=False, type='list'),
_top_dir=dict(required=True),
_ca_subject=dict(required=True),
_subject_base=dict(required=True),
dirman_password=dict(required=True, no_log=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
config_ca_host_name=dict(required=True),
config_ips=dict(required=False, type='list', default=[]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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)
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-v1.7.0/roles/ipareplica/library/ipareplica_setup_certmonger.py 0000664 0000000 0000000 00000003662 14232747165 0030006 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
options:
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, setup_logging, redirect_stdout, configure_certmonger
)
def main():
ansible_module = AnsibleModule(
argument_spec={},
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_setup_custodia.py 0000664 0000000 0000000 00000015667 14232747165 0027464 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
no_ui_redirect:
description: Do not automatically redirect to the Web UI
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
ccache:
description: The local ccache
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description: The installer _ca_file setting
required: yes
_kra_enabled:
description: The installer _kra_enabled setting
required: yes
_kra_host_name:
description: The installer _kra_host_name setting
required: yes
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
author:
- Thomas 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,
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),
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_kra_enabled=dict(required=False, type='bool'),
_kra_host_name=dict(required=False),
_pkinit_pkcs12_info=dict(required=False, type='list'),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_setup_dns.py 0000664 0000000 0000000 00000013656 14232747165 0026431 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
zonemgr:
description: DNS zone manager e-mail address. Defaults to hostmaster@DOMAIN
required: yes
forwarders:
description: Add DNS forwarders
required: yes
forward_policy:
description: DNS forwarding policy for global forwarders
required: yes
no_dnssec_validation:
description: Disable DNSSEC validation
required: yes
dns_ip_addresses:
description: The dns ip_addresses setting
required: no
dns_reverse_zones:
description: The dns reverse_zones setting
required: no
ccache:
description: The local ccache
required: no
_top_dir:
description: The installer _top_dir setting
required: no
setup_ca:
description: Configure a dogtag CA
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
author:
- Thomas 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,
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),
# dns
zonemgr=dict(required=False),
forwarders=dict(required=False, type='list', default=[]),
forward_policy=dict(default=None, choices=['first', 'only']),
no_dnssec_validation=dict(required=False, type='bool',
default=False),
# additional
dns_ip_addresses=dict(required=True, type='list'),
dns_reverse_zones=dict(required=True, type='list'),
ccache=dict(required=True),
_top_dir=dict(required=True),
setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_setup_ds.py 0000664 0000000 0000000 00000032760 14232747165 0026250 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
password:
description: Admin user kerberos password
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
realm:
description: Kerberos realm name of the IPA deployment
required: yes
hostname:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
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
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
force_join:
description: Force client enrollment even if already enrolled
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
server:
description: Fully qualified name of IPA server to enroll to
required: no
ccache:
description: The local ccache
required: no
installer_ccache:
description: The installer ccache setting
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
_add_to_ipaservers:
description: The installer _add_to_ipaservers setting
required: no
_ca_subject:
description: The installer _ca_subject setting
required: no
_subject_base:
description: The installer _subject_base setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
config_setup_ca:
description: The config setup_ca setting
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
config_ca_host_name:
description: The config ca_host_name setting
required: no
config_ips:
description: The config ips setting
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
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
)
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', default=[]),
domain=dict(required=False),
realm=dict(required=False),
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', 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),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', default=[]),
# client
force_join=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True),
# additional
server=dict(required=True),
ccache=dict(required=True),
installer_ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_dirsrv_pkcs12_info=dict(required=False, type='list'),
_top_dir=dict(required=True),
_add_to_ipaservers=dict(required=True, type='bool'),
_ca_subject=dict(required=True),
_subject_base=dict(required=True),
dirman_password=dict(required=True, no_log=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
config_ca_host_name=dict(required=True),
config_ips=dict(required=False, type='list', default=[]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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 = inspect.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 = inspect.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-v1.7.0/roles/ipareplica/library/ipareplica_setup_http.py 0000664 0000000 0000000 00000020150 14232747165 0026607 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
no_ui_redirect:
description: Do not automatically redirect to the Web UI
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
config_ca_host_name:
description: The config ca_host_name setting
required: no
ccache:
description: The local ccache
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description: The installer _ca_file setting
required: yes
_http_pkcs12_info:
description: The installer _http_pkcs12_info setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
import inspect
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, create_ipa_conf,
install_http
)
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),
config_master_host_name=dict(required=True),
config_ca_host_name=dict(required=True),
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_http_pkcs12_info=dict(required=False, type='list'),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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 = inspect.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-v1.7.0/roles/ipareplica/library/ipareplica_setup_kra.py 0000664 0000000 0000000 00000024761 14232747165 0026421 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
password:
description: Admin user kerberos password
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
realm:
description: Kerberos realm name of the IPA deployment
required: yes
hostname:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
pki_config_override:
description: Path to ini file with config overrides
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
force_join:
description: Force client enrollment even if already enrolled
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
server:
description: Fully qualified name of IPA server to enroll to
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
installer_ccache:
description: The installer ccache setting
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_kra_enabled:
description: The installer _kra_enabled setting
required: yes
_kra_host_name:
description: The installer _kra_host_name setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
_add_to_ipaservers:
description: The installer _add_to_ipaservers setting
required: no
_ca_subject:
description: The installer _ca_subject setting
required: no
_subject_base:
description: The installer _subject_base setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
author:
- Thomas 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,
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, no_log=True),
password=dict(required=False, no_log=True),
ip_addresses=dict(required=False, type='list', default=[]),
domain=dict(required=False),
realm=dict(required=False),
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
pki_config_override=dict(required=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', default=[]),
# client
force_join=dict(required=False, type='bool'),
# certificate system
subject_base=dict(required=True),
# additional
server=dict(required=True),
config_master_host_name=dict(required=True),
installer_ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_kra_enabled=dict(required=False, type='bool'),
_kra_host_name=dict(required=False),
_ca_host_name=dict(required=False),
_top_dir=dict(required=True),
_add_to_ipaservers=dict(required=True, type='bool'),
_ca_subject=dict(required=True),
_subject_base=dict(required=True),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_setup_krb.py 0000664 0000000 0000000 00000013336 14232747165 0026416 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
ccache:
description: The local ccache
required: no
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
import inspect
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, api, redirect_stdout, install_krb
)
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),
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_pkinit_pkcs12_info=dict(required=False, type='list'),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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 = inspect.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-v1.7.0/roles/ipareplica/library/ipareplica_setup_otpd.py 0000664 0000000 0000000 00000012106 14232747165 0026600 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
no_ui_redirect:
description: Do not automatically redirect to the Web UI
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
ccache:
description: The local ccache
required: no
_ca_file:
description: The installer _ca_file setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
author:
- Thomas 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,
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),
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_ca_file=dict(required=False),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipareplica/library/ipareplica_test.py 0000664 0000000 0000000 00000044752 14232747165 0025405 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
servers:
description: Fully qualified name of IPA servers to enroll to
required: yes
realm:
description: Kerberos realm name of the IPA deployment
required: yes
hostname:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
required: yes
hidden_replica:
description: Install a hidden replica
required: yes
skip_mem_check:
description: Skip checking for minimum required memory
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
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
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
http_cert_files:
description:
File containing the Apache Server SSL certificate and private key
required: yes
pkinit_cert_files:
description:
File containing the Kerberos KDC SSL certificate and private key
required: yes
no_ntp:
description: Do not configure ntp
required: yes
ntp_servers:
description: ntp servers to use
required: yes
ntp_pool:
description: ntp server pool to use
required: yes
no_reverse:
description: Do not create new reverse DNS zone
required: yes
auto_reverse:
description: Create necessary reverse zones
required: yes
forwarders:
description: Add DNS forwarders
required: yes
no_forwarders:
description: Do not add any DNS forwarders, use root servers instead
required: yes
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
required: yes
forward_policy:
description: DNS forwarding policy for global forwarders
required: yes
no_dnssec_validation:
description: Disable DNSSEC validation
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import (
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
)
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', default=[]),
domain=dict(required=False),
servers=dict(required=False, type='list', default=[]),
realm=dict(required=False),
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', 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),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', default=[]),
http_cert_files=dict(required=False, type='list', default=[]),
pkinit_cert_files=dict(required=False, type='list', default=[]),
# client
no_ntp=dict(required=False, type='bool', default=False),
ntp_servers=dict(required=False, type='list', default=[]),
ntp_pool=dict(required=False),
# 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', default=[]),
no_forwarders=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
forward_policy=dict(default=None, choices=['first', 'only']),
no_dnssec_validation=dict(required=False, type='bool',
default=False),
),
)
ansible_module._ansible_debug = True
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")
# 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 = inspect.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 {!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 = inspect.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")
# 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,
)
if __name__ == '__main__':
main()
ansible-freeipa-v1.7.0/roles/ipareplica/meta/ 0000775 0000000 0000000 00000000000 14232747165 0021131 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipareplica/meta/main.yml 0000664 0000000 0000000 00000000514 14232747165 0022600 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.8
platforms:
- name: Fedora
versions:
- all
- name: EL
versions:
- 7
- 8
galaxy_tags:
- identity
- ipa
- freeipa
ansible-freeipa-v1.7.0/roles/ipareplica/module_utils/ 0000775 0000000 0000000 00000000000 14232747165 0022710 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipareplica/module_utils/ansible_ipa_replica.py 0000664 0000000 0000000 00000042135 14232747165 0027234 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-replica-install code
#
# Copyright (C) 2018 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"]
import sys
# HACK: workaround for Ansible 2.9
# https://github.com/ansible/ansible/issues/68361
if 'ansible.executor' in sys.modules:
for attr in __all__:
setattr(sys.modules[__name__], attr, None)
else:
import logging
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)
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 Exception("freeipa version '%s' is too old" % VERSION)
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)
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://{}/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://{}/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
ansible-freeipa-v1.7.0/roles/ipareplica/tasks/ 0000775 0000000 0000000 00000000000 14232747165 0021330 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipareplica/tasks/install.yml 0000664 0000000 0000000 00000111654 14232747165 0023531 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipareplica
- block:
- name: Install - Ensure IPA replica packages are installed
package:
name: "{{ ipareplica_packages }}"
state: present
- name: Install - Ensure IPA replica packages for dns are installed
package:
name: "{{ ipareplica_packages_dns }}"
state: present
when: ipareplica_setup_dns | bool
- name: Install - Ensure IPA replica packages for adtrust are installed
package:
name: "{{ ipareplica_packages_adtrust }}"
state: present
when: ipareplica_setup_adtrust | bool
- name: Install - Ensure that firewall packages installed
package:
name: "{{ ipareplica_packages_firewalld }}"
state: present
when: ipareplica_setup_firewalld | bool
when: ipareplica_install_packages | bool
- block:
- name: Firewalld service - Ensure that firewalld is running
systemd:
name: firewalld
enabled: yes
state: started
- name: Firewalld - Verify runtime zone "{{ ipareplica_firewalld_zone }}"
shell: >
firewall-cmd
--info-zone="{{ ipareplica_firewalld_zone }}"
>/dev/null
when: ipareplica_firewalld_zone is defined
- name: Firewalld - Verify permanent zone "{{ ipareplica_firewalld_zone }}"
shell: >
firewall-cmd
--permanent
--info-zone="{{ ipareplica_firewalld_zone }}"
>/dev/null
when: ipareplica_firewalld_zone is defined
when: ipareplica_setup_firewalld | bool
- name: Install - Set ipareplica_servers
set_fact:
ipareplica_servers: "{{ groups['ipaservers'] | list }}"
when: groups.ipaservers is defined and ipareplica_servers is not defined
- name: Install - Set default principal if no keytab is given
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
- 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
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_no_ntp: "{{ result_ipareplica_test.ipa_python_version
< 40690 }}"
ipaclient_install_packages: "{{ ipareplica_install_packages }}"
when: not result_ipareplica_test.client_enrolled
- name: Install - Configure firewalld
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
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 }}"
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
set_fact:
ipareplica_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 }}"
### ad trust ###
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 }}"
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: "{{ ipareplica_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 }}"
### ad trust ###
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 }}"
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: "{{ ipareplica_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 }}"
### ad trust ###
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 }}"
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: "{{ ipareplica_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: "{{ ipareplica_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 }}"
### ad trust ###
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 }}"
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: "{{ ipareplica_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: "{{ ipareplica_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: "{{ ipareplica_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 }}"
### ad trust ###
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 }}"
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: "{{ ipareplica_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: "{{ ipareplica_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: "{{ ipareplica_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 }}"
dirman_password: "{{ ipareplica_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: "{{ ipareplica_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: "{{ ipareplica_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: "{{ ipareplica_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: "{{ ipareplica_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: "{{ ipareplica_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 }}"
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
- 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
- name: Install - Cleanup root IPA cache
file:
path: "/root/.ipa_cache"
state: absent
when: result_ipareplica_enable_ipa.changed
always:
- name: Cleanup temporary files
file:
path: "{{ item }}"
state: absent
with_items:
- "/etc/ipa/.tmp_pkcs12_dirsrv"
- "/etc/ipa/.tmp_pkcs12_http"
- "/etc/ipa/.tmp_pkcs12_pkinit"
when: not ansible_check_mode and
not (result_ipareplica_test.client_already_configured is defined or
result_ipareplica_test.server_already_configured is defined)
ansible-freeipa-v1.7.0/roles/ipareplica/tasks/main.yml 0000664 0000000 0000000 00000002216 14232747165 0023000 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipareplica
- name: Import variables specific to distribution
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
include_tasks: install.yml
when: state|default('present') == 'present'
- name: Uninstall IPA replica
include_tasks: uninstall.yml
when: state|default('present') == 'absent'
ansible-freeipa-v1.7.0/roles/ipareplica/tasks/uninstall.yml 0000664 0000000 0000000 00000002256 14232747165 0024071 0 ustar 00root root 0000000 0000000 ---
# tasks to uninstall IPA replica
- name: Uninstall - Uninstall IPA replica
command: >
/usr/sbin/ipa-server-install
--uninstall
-U
{{ "--ignore-topology-disconnect" if
ipareplica_ignore_topology_disconnect | bool else "" }}
{{ "--ignore-last-of-role" if ipareplica_ignore_last_of_role | bool
else "" }}
register: result_uninstall
# 2 means that uninstall failed because IPA replica was not configured
failed_when: result_uninstall.rc != 0 and "'Env' object
has no attribute 'basedn'" not in result_uninstall.stderr
# IPA server is not configured on this system" not in
# result_uninstall.stdout_lines
changed_when: result_uninstall.rc == 0
# until: result_uninstall.rc == 0
retries: 2
delay: 1
#- name: Uninstall - Remove all replication agreements and data about replica
# command: >
# /usr/sbin/ipa-replica-manage
# del
# {{ ipareplica_hostname | default(ansible_facts['fqdn']) }}
# --force
# --password={{ ipadm_password }}
# failed_when: False
# delegate_to: "{{ groups.ipaserver[0] | default(fail) }}"
#- name: Remove IPA replica packages
# package:
# name: "{{ ipareplica_packages }}"
# state: absent
ansible-freeipa-v1.7.0/roles/ipareplica/vars/ 0000775 0000000 0000000 00000000000 14232747165 0021156 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipareplica/vars/Fedora-25.yml 0000664 0000000 0000000 00000000407 14232747165 0023326 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-v1.7.0/roles/ipareplica/vars/Fedora-26.yml 0000664 0000000 0000000 00000000407 14232747165 0023327 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-v1.7.0/roles/ipareplica/vars/Fedora-27.yml 0000664 0000000 0000000 00000000407 14232747165 0023330 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-v1.7.0/roles/ipareplica/vars/Fedora.yml 0000664 0000000 0000000 00000000421 14232747165 0023076 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-v1.7.0/roles/ipareplica/vars/RedHat-7.yml 0000664 0000000 0000000 00000000406 14232747165 0023214 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-v1.7.0/roles/ipareplica/vars/RedHat-8.yml 0000664 0000000 0000000 00000000361 14232747165 0023215 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-v1.7.0/roles/ipareplica/vars/Ubuntu-18.04.yml 0000664 0000000 0000000 00000000700 14232747165 0023630 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-v1.7.0/roles/ipareplica/vars/Ubuntu.yml 0000664 0000000 0000000 00000000373 14232747165 0023166 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-v1.7.0/roles/ipareplica/vars/default.yml 0000664 0000000 0000000 00000000422 14232747165 0023323 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-v1.7.0/roles/ipaserver/ 0000775 0000000 0000000 00000000000 14232747165 0020072 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaserver/README.md 0000664 0000000 0000000 00000030741 14232747165 0021356 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+
* Fedora 26+
* Ubuntu
Requirements
------------
**Controller**
* Ansible version: 2.8+
**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 client(s) 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.
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
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_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
Authors
=======
Thomas Woerner
ansible-freeipa-v1.7.0/roles/ipaserver/defaults/ 0000775 0000000 0000000 00000000000 14232747165 0021701 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaserver/defaults/main.yml 0000664 0000000 0000000 00000001773 14232747165 0023360 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
### 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
ansible-freeipa-v1.7.0/roles/ipaserver/library/ 0000775 0000000 0000000 00000000000 14232747165 0021536 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaserver/library/ipaserver_enable_ipa.py 0000664 0000000 0000000 00000007321 14232747165 0026252 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-server-install code
#
# Copyright (C) 2017 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
required: yes
setup_dns:
description: Configure bind with our zone
required: no
setup_ca:
description: Configure a dogtag CA
required: no
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
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),
setup_dns=dict(required=True, type='bool'),
setup_ca=dict(required=True, type='bool'),
),
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipaserver/library/ipaserver_load_cache.py 0000664 0000000 0000000 00000005436 14232747165 0026242 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
setup_logging, options, paths, read_cache
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=True, no_log=True),
),
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipaserver/library/ipaserver_master_password.py 0000664 0000000 0000000 00000005361 14232747165 0027412 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-server-install code
#
# Copyright (C) 2017 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
required: no
master_password:
description: kerberos master password (normally autogenerated)
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
password:
description: The master password
returned: always
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
setup_logging, options, paths, read_cache, ipa_generate_password
)
def main():
module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=True, no_log=True),
master_password=dict(required=False, no_log=True),
),
supports_check_mode=True,
)
module._ansible_debug = True
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-v1.7.0/roles/ipaserver/library/ipaserver_prepare.py 0000664 0000000 0000000 00000036735 14232747165 0025644 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: yes
dm_password:
description: Directory Manager password
required: no
password:
description: Admin user kerberos password
required: no
ip_addresses:
description: List of Master Server IP Addresses
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
external_ca:
description: External ca setting
required: yes
external_ca_type:
description: Type of the external CA
required: yes
external_ca_profile:
description:
Specify the certificate profile/template to use at the external CA
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: yes
ca_subject:
description: The installer ca_subject setting
required: yes
allow_zone_overlap:
description: Create DNS zone even if it already exists
required: yes
reverse_zones:
description: The reverse DNS zones to use
required: yes
no_reverse:
description: Do not create new reverse DNS zone
required: yes
auto_reverse:
description: Create necessary reverse zones
required: yes
forwarders:
description: Add DNS forwarders
required: yes
no_forwarders:
description: Do not add any DNS forwarders, use root servers instead
required: yes
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
required: yes
forward_policy:
description: DNS forwarding policy for global forwarders
required: yes
no_dnssec_validation:
description: Disable DNSSEC validation
required: yes
enable_compat:
description: Enable support for trusted domains for old clients
required: yes
netbios_name:
description: NetBIOS name of the IPA domain
required: yes
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
required: yes
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
_hostname_overridden:
description: The installer _hostname_overridden setting
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
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, no_log=True),
password=dict(required=True, no_log=True),
ip_addresses=dict(required=False, type='list', default=[]),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', 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),
external_ca_profile=dict(required=False),
external_cert_files=dict(required=False, type='list', default=[]),
subject_base=dict(required=False),
ca_subject=dict(required=False),
# dns
allow_zone_overlap=dict(required=False, type='bool',
default=False),
reverse_zones=dict(required=False, type='list', 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', default=[]),
no_forwarders=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
forward_policy=dict(default=None, choices=['first', 'only']),
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),
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),
_hostname_overridden=dict(required=False, type='bool',
default=False),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
setup_logging()
ansible_log = AnsibleModuleLog(ansible_module)
# initialize return values for flake ############################
# These are set by ca.install_check
options._subject_base = None
options._ca_subject = None
# 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._host_name_overridden = ansible_module.params.get(
'_hostname_overridden')
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:
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,
# 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-v1.7.0/roles/ipaserver/library/ipaserver_set_ds_password.py 0000664 0000000 0000000 00000015453 14232747165 0027403 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
password:
description: Admin user kerberos password
required: no
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: no
setup_ca:
description: Configure a dogtag CA
required: no
idstart:
description: The starting value for the IDs range (default random)
required: no
idmax:
description: The max value for the IDs range (default idstart+199999)
required: no
no_hbac_allow:
description: Don't install allow_all HBAC rule
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
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
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: yes
ca_subject:
description: The installer ca_subject setting
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
domainlevel:
description: The domain level
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
MAX_DOMAIN_LEVEL, AnsibleModuleLog, options, sysrestore, paths,
api_Backend_ldap2, ds_init_info, redirect_stdout, setup_logging
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
dm_password=dict(required=True, no_log=True),
password=dict(required=True, no_log=True),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=True),
# 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),
_dirsrv_pkcs12_info=dict(required=False, type='list'),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', default=[]),
subject_base=dict(required=False),
ca_subject=dict(required=False),
# certificate system
external_cert_files=dict(required=False, type='list', default=[]),
# additional
domainlevel=dict(required=False, type='int',
default=MAX_DOMAIN_LEVEL),
),
)
ansible_module._ansible_debug = True
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)
# done ##########################################################
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-v1.7.0/roles/ipaserver/library/ipaserver_setup_adtrust.py 0000664 0000000 0000000 00000010177 14232747165 0027104 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
enable_compat:
description: Enable support for trusted domains for old clients
required: yes
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
required: yes
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
required: yes
adtrust_netbios_name:
description: The adtrust netbios_name setting
required: no
adtrust_reset_netbios_name:
description: The adtrust reset_netbios_name setting
required: no
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
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),
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),
adtrust_reset_netbios_name=dict(required=True, type='bool'),
),
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipaserver/library/ipaserver_setup_ca.py 0000664 0000000 0000000 00000032152 14232747165 0025776 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
password:
description: Admin user kerberos password
required: no
master_password:
description: kerberos master password (normally autogenerated)
required: no
ip_addresses:
description: List of Master Server IP Addresses
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
pki_config_override:
description: Path to ini file with config overrides
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
idstart:
description: The starting value for the IDs range (default random)
required: no
idmax:
description: The max value for the IDs range (default idstart+199999)
required: no
no_hbac_allow:
description: Don't install allow_all HBAC rule
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
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
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
external_ca:
description: External ca setting
required: yes
external_ca_type:
description: Type of the external CA
required: yes
external_ca_profile:
description:
Specify the certificate profile/template to use at the external CA
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: yes
_subject_base:
description: The installer _subject_base setting
required: yes
ca_subject:
description: The installer ca_subject setting
required: yes
_ca_subject:
description: The installer _ca_subject setting
required: yes
ca_signing_algorithm:
description: Signing algorithm of the IPA CA certificate
required: yes
reverse_zones:
description: The reverse DNS zones to use
required: yes
no_reverse:
description: Do not create new reverse DNS zone
required: yes
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
required: yes
domainlevel:
description: The domain level
required: yes
_http_ca_cert:
description: The installer _http_ca_cert setting
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
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, no_log=True),
password=dict(required=True, no_log=True),
master_password=dict(required=True, no_log=True),
ip_addresses=dict(required=False, type='list', default=[]),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=False),
no_host_dns=dict(required=False, type='bool', default=False),
pki_config_override=dict(required=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),
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),
dirsrv_cert_files=dict(required=False, type='list'),
_dirsrv_pkcs12_info=dict(required=False, type='list'),
# certificate system
external_ca=dict(required=False, type='bool', default=False),
external_ca_type=dict(required=False),
external_ca_profile=dict(required=False),
external_cert_files=dict(required=False, type='list',
default=None),
subject_base=dict(required=False),
_subject_base=dict(required=False),
ca_subject=dict(required=False),
_ca_subject=dict(required=False),
ca_signing_algorithm=dict(required=False),
# dns
reverse_zones=dict(required=False, type='list', 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),
),
)
ansible_module._ansible_debug = True
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')
# 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 CA ##############################################################
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)
custodia.set_output(ansible_log)
with redirect_stdout(ansible_log):
custodia.create_instance()
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-v1.7.0/roles/ipaserver/library/ipaserver_setup_custodia.py 0000664 0000000 0000000 00000006446 14232747165 0027235 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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_custodia
short description: Setup custodia
description: Setup custodia
options:
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
setup_logging, AnsibleModuleLog, options,
api_Backend_ldap2,
custodiainstance, redirect_stdout
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
realm=dict(required=True),
hostname=dict(required=False),
setup_ca=dict(required=False, type='bool', default=False),
),
)
ansible_module._ansible_debug = True
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')
options.promote = False
# init ##################################################################
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
# 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()
# done ##################################################################
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()
ansible-freeipa-v1.7.0/roles/ipaserver/library/ipaserver_setup_dns.py 0000664 0000000 0000000 00000012714 14232747165 0026201 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: no
setup_dns:
description: Configure bind with our zone
required: no
setup_ca:
description: Configure a dogtag CA
required: no
zonemgr:
description: DNS zone manager e-mail address. Defaults to hostmaster@DOMAIN
required: yes
forwarders:
description: Add DNS forwarders
required: no
forward_policy:
description: DNS forwarding policy for global forwarders
required: yes
no_dnssec_validation:
description: Disable DNSSEC validation
required: yes
dns_ip_addresses:
description: The dns ip_addresses setting
required: no
dns_reverse_zones:
description: The dns reverse_zones setting
required: no
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
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', default=[]),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=True),
# server
setup_dns=dict(required=True, type='bool'),
setup_ca=dict(required=True, type='bool'),
# dns
zonemgr=dict(required=False),
forwarders=dict(required=True, type='list'),
forward_policy=dict(default='first', choices=['first', 'only']),
no_dnssec_validation=dict(required=False, type='bool',
default=False),
# additional
dns_ip_addresses=dict(required=True, type='list'),
dns_reverse_zones=dict(required=True, type='list'),
),
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipaserver/library/ipaserver_setup_ds.py 0000664 0000000 0000000 00000017760 14232747165 0026031 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
password:
description: Admin user kerberos password
required: no
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: yes
idstart:
description: The starting value for the IDs range (default random)
required: no
idmax:
description: The max value for the IDs range (default idstart+199999)
required: no
no_hbac_allow:
description: Don't install allow_all HBAC rule
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
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
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: yes
ca_subject:
description: The installer ca_subject setting
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
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, no_log=True),
password=dict(required=True, no_log=True),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=False),
# 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),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', default=[]),
_dirsrv_pkcs12_info=dict(required=False, type='list'),
# certificate system
external_cert_files=dict(required=False, type='list', default=[]),
subject_base=dict(required=False),
ca_subject=dict(required=False),
# additional
setup_ca=dict(required=False, type='bool', default=False),
),
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipaserver/library/ipaserver_setup_http.py 0000664 0000000 0000000 00000027245 14232747165 0026401 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
password:
description: Admin user kerberos password
required: no
master_password:
description: kerberos master password (normally autogenerated)
required: no
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: yes
reverse_zones:
description: The reverse DNS zones to use
required: yes
http_cert_files:
description:
File containing the Apache Server SSL certificate and private key
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
no_hbac_allow:
description: Don't install allow_all HBAC rule
required: yes
no_ui_redirect:
description: Do not automatically redirect to the Web UI
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: yes
_subject_base:
description: The installer _subject_base setting
required: yes
ca_subject:
description: The installer ca_subject setting
required: yes
_ca_subject:
description: The installer _ca_subject setting
required: yes
idstart:
description: The starting value for the IDs range (default random)
required: no
idmax:
description: The max value for the IDs range (default idstart+199999)
required: no
domainlevel:
description: The domain level
required: yes
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
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
no_reverse:
description: Do not create new reverse DNS zone
required: yes
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
_http_pkcs12_info:
description: The installer _http_pkcs12_info setting
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
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, no_log=True),
password=dict(required=True, no_log=True),
master_password=dict(required=True, no_log=True),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=False),
ip_addresses=dict(required=False, type='list', default=[]),
reverse_zones=dict(required=False, type='list', default=[]),
http_cert_files=dict(required=False, type='list', 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', default=[]),
subject_base=dict(required=False),
_subject_base=dict(required=False),
ca_subject=dict(required=False),
_ca_subject=dict(required=False),
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', 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'),
_http_pkcs12_info=dict(required=False, type='list'),
),
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipaserver/library/ipaserver_setup_kra.py 0000664 0000000 0000000 00000007460 14232747165 0026174 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
hostname:
description: Fully qualified name of this host
required: no
setup_ca:
description: Configure a dogtag CA
required: no
setup_kra:
description: Configure a dogtag KRA
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
pki_config_override:
description: Path to ini file with config overrides
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
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, no_log=True),
hostname=dict(required=True),
setup_ca=dict(required=True, type='bool'),
setup_kra=dict(required=True, type='bool'),
realm=dict(required=True),
pki_config_override=dict(required=False),
),
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipaserver/library/ipaserver_setup_krb.py 0000664 0000000 0000000 00000020017 14232747165 0026166 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
password:
description: Admin user kerberos password
required: no
master_password:
description: kerberos master password (normally autogenerated)
required: no
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: yes
reverse_zones:
description: The reverse DNS zones to use
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
no_hbac_allow:
description: Don't install allow_all HBAC rule
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: yes
ca_subject:
description: The installer ca_subject setting
required: yes
idstart:
description: The starting value for the IDs range (default random)
required: no
idmax:
description: The max value for the IDs range (default idstart+199999)
required: no
no_reverse:
description: Do not create new reverse DNS zone
required: yes
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
required: yes
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
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, no_log=True),
password=dict(required=True, no_log=True),
master_password=dict(required=True, no_log=True),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=False),
ip_addresses=dict(required=False, type='list', default=[]),
reverse_zones=dict(required=False, type='list', 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', default=[]),
subject_base=dict(required=False),
ca_subject=dict(required=False),
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'),
),
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipaserver/library/ipaserver_setup_ntp.py 0000664 0000000 0000000 00000007410 14232747165 0026213 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: yes
ntp_pool:
description: ntp server pool to use
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
AnsibleModuleLog, setup_logging, options, sysrestore, paths,
redirect_stdout, time_service, sync_time, ntpinstance, timeconf
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
ntp_servers=dict(required=False, type='list', default=None),
ntp_pool=dict(required=False, default=None),
),
)
ansible_module._ansible_debug = True
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 = inspect.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-v1.7.0/roles/ipaserver/library/ipaserver_setup_otpd.py 0000664 0000000 0000000 00000005563 14232747165 0026367 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: no
hostname:
description: Fully qualified name of this host
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import (
AnsibleModuleLog, setup_logging, options,
api_Backend_ldap2, redirect_stdout, otpdinstance, ipautil
)
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# basic
realm=dict(required=True),
hostname=dict(required=False),
setup_ca=dict(required=False, type='bool', default=False),
),
)
ansible_module._ansible_debug = True
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-v1.7.0/roles/ipaserver/library/ipaserver_test.py 0000664 0000000 0000000 00000127670 14232747165 0025164 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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
required: yes
dm_password:
description: Directory Manager password
required: no
password:
description: Admin user kerberos password
required: no
master_password:
description: kerberos master password (normally autogenerated)
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
realm:
description: Kerberos realm name of the IPA deployment
required: yes
hostname:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
pki_config_override:
description: Path to ini file with config overrides
required: yes
skip_mem_check:
description: Skip checking for minimum required memory
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
idstart:
description: The starting value for the IDs range (default random)
required: yes
idmax:
description: The max value for the IDs range (default idstart+199999)
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
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
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
http_cert_files:
description:
File containing the Apache Server SSL certificate and private key
required: yes
pkinit_cert_files:
description:
File containing the Kerberos KDC SSL certificate and private key
required: yes
dirsrv_pin:
description: The password to unlock the Directory Server private key
required: yes
http_pin:
description: The password to unlock the Apache Server private key
required: yes
pkinit_pin:
description: The password to unlock the Kerberos KDC private key
required: yes
dirsrv_cert_name:
description: Name of the Directory Server SSL certificate to install
required: yes
http_cert_name:
description: Name of the Apache Server SSL certificate to install
required: yes
pkinit_cert_name:
description: Name of the Kerberos KDC SSL certificate to install
required: yes
ntp_servers:
description: ntp servers to use
required: yes
ntp_pool:
description: ntp server pool to use
required: yes
no_ntp:
description: Do not configure ntp
required: yes
external_ca:
description: External ca setting
required: yes
external_ca_type:
description: Type of the external CA
required: yes
external_ca_profile:
description:
Specify the certificate profile/template to use at the external CA
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
subject_base:
description:
The certificate subject base (default O=).
RDNs are in LDAP order (most specific RDN first).
required: yes
ca_subject:
description: The installer ca_subject setting
required: yes
allow_zone_overlap:
description: Create DNS zone even if it already exists
required: yes
reverse_zones:
description: The reverse DNS zones to use
required: yes
no_reverse:
description: Do not create new reverse DNS zone
required: yes
auto_reverse:
description: Create necessary reverse zones
required: yes
zonemgr:
description: DNS zone manager e-mail address. Defaults to hostmaster@DOMAIN
required: yes
forwarders:
description: Add DNS forwarders
required: yes
no_forwarders:
description: Do not add any DNS forwarders, use root servers instead
required: yes
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
required: yes
forward_policy:
description: DNS forwarding policy for global forwarders
required: yes
no_dnssec_validation:
description: Disable DNSSEC validation
required: yes
enable_compat:
description: Enable support for trusted domains for old clients
required: yes
netbios_name:
description: NetBIOS name of the IPA domain
required: yes
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
required: yes
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
required: yes
author:
- Thomas Woerner
'''
EXAMPLES = '''
'''
RETURN = '''
'''
import os
import sys
import inspect
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 (
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
)
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, no_log=True),
password=dict(required=True, no_log=True),
master_password=dict(required=False, no_log=True),
domain=dict(required=False),
realm=dict(required=False),
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
pki_config_override=dict(required=False),
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),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', default=None),
http_cert_files=dict(required=False, type='list', default=None),
pkinit_cert_files=dict(required=False, type='list', default=None),
dirsrv_pin=dict(required=False),
http_pin=dict(required=False),
pkinit_pin=dict(required=False),
dirsrv_cert_name=dict(required=False),
http_cert_name=dict(required=False),
pkinit_cert_name=dict(required=False),
# client
# mkhomedir
ntp_servers=dict(required=False, type='list', default=None),
ntp_pool=dict(required=False, 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),
external_ca_profile=dict(required=False),
external_cert_files=dict(required=False, type='list',
default=None),
subject_base=dict(required=False),
ca_subject=dict(required=False),
# ca_signing_algorithm
# dns
allow_zone_overlap=dict(required=False, type='bool',
default=False),
reverse_zones=dict(required=False, type='list', default=[]),
no_reverse=dict(required=False, type='bool', default=False),
auto_reverse=dict(required=False, type='bool', default=False),
zonemgr=dict(required=False),
forwarders=dict(required=False, type='list', default=[]),
no_forwarders=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
forward_policy=dict(default=None, choices=['first', 'only']),
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),
rid_base=dict(required=False, type='int', default=1000),
secondary_rid_base=dict(required=False, type='int',
default=100000000),
# additional
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
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')
# 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 ######################################################
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")
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))
# 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")
if self.netbios_name:
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 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()
if not options.realm_name:
realm_name = domain_name.upper()
else:
realm_name = options.realm_name.upper()
# pylint: disable=deprecated-method
argspec = inspect.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: {}".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=options.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)
if __name__ == '__main__':
main()
ansible-freeipa-v1.7.0/roles/ipaserver/meta/ 0000775 0000000 0000000 00000000000 14232747165 0021020 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaserver/meta/main.yml 0000664 0000000 0000000 00000000513 14232747165 0022466 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.8
platforms:
- name: Fedora
versions:
- all
- name: EL
versions:
- 7
- 8
galaxy_tags:
- identity
- ipa
- freeipa
ansible-freeipa-v1.7.0/roles/ipaserver/module_utils/ 0000775 0000000 0000000 00000000000 14232747165 0022577 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaserver/module_utils/ansible_ipa_server.py 0000664 0000000 0000000 00000035037 14232747165 0027015 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Based on ipa-client-install code
#
# Copyright (C) 2017 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__ = ["IPAChangeConf", "certmonger", "sysrestore", "root_logger",
"ipa_generate_password", "run", "ScriptError", "services",
"tasks", "errors", "x509", "DOMAIN_LEVEL_0", "MIN_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"]
import sys
# HACK: workaround for Ansible 2.9
# https://github.com/ansible/ansible/issues/68361
if 'ansible.executor' in sys.modules:
for attr in __all__:
setattr(sys.modules[__name__], attr, None)
else:
import logging
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
except ImportError:
from ipalib.x509 import load_certificate
load_pem_x509_certificate = None
else:
# IPA version < 4.5
raise Exception("freeipa version '%s' is too old" % VERSION)
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)
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-----"
if load_pem_x509_certificate is not None:
cert = load_pem_x509_certificate(cert.encode('utf-8'))
else:
cert = load_certificate(cert.encode('utf-8'))
else:
cert = base64.b64decode(cert)
return cert
ansible-freeipa-v1.7.0/roles/ipaserver/tasks/ 0000775 0000000 0000000 00000000000 14232747165 0021217 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaserver/tasks/copy_external_cert.yml 0000664 0000000 0000000 00000001075 14232747165 0025636 0 ustar 00root root 0000000 0000000 ---
- name: Install - Initialize ipaserver_external_cert_files
set_fact:
ipaserver_external_cert_files: []
when: ipaserver_external_cert_files is undefined
- name: Install - Copy "{{ item }}" "{{ inventory_hostname }}':/root/'{{ item | basename }}"
copy:
src: "{{ item }}"
dest: "/root/{{ item | basename }}"
mode: preserve
force: yes
- name: Install - Extend ipaserver_external_cert_files with "/root/{{ item | basename }}"
set_fact:
ipaserver_external_cert_files: "{{ ipaserver_external_cert_files }} + [ '/root/{{ item | basename }}' ]"
ansible-freeipa-v1.7.0/roles/ipaserver/tasks/install.yml 0000664 0000000 0000000 00000053204 14232747165 0023414 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipaserver
- block:
- name: Install - Ensure that IPA server packages are installed
package:
name: "{{ ipaserver_packages }}"
state: present
- name: Install - Ensure that IPA server packages for dns are installed
package:
name: "{{ ipaserver_packages_dns }}"
state: present
when: ipaserver_setup_dns | bool
- name: Install - Ensure that IPA server packages for adtrust are installed
package:
name: "{{ ipaserver_packages_adtrust }}"
state: present
when: ipaserver_setup_adtrust | bool
- name: Install - Ensure that firewall packages installed
package:
name: "{{ ipaserver_packages_firewalld }}"
state: present
when: ipaserver_setup_firewalld | bool
when: ipaserver_install_packages | bool
- block:
- name: Firewalld service - Ensure that firewalld is running
systemd:
name: firewalld
enabled: yes
state: started
- name: Firewalld - Verify runtime zone "{{ ipaserver_firewalld_zone }}"
shell: >
firewall-cmd
--info-zone="{{ ipaserver_firewalld_zone }}"
>/dev/null
when: ipaserver_firewalld_zone is defined
- name: Firewalld - Verify permanent zone "{{ ipaserver_firewalld_zone }}"
shell: >
firewall-cmd
--permanent
--info-zone="{{ ipaserver_firewalld_zone }}"
>/dev/null
when: ipaserver_firewalld_zone is defined
when: ipaserver_setup_firewalld | bool
- 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) }}"
# 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
- block:
# This block is executed only 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 - 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
set_fact:
ipaserver_master_password:
"{{ result_ipaserver_master_password.password }}"
when: ipaserver_master_password is undefined
- 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 }}"
_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: "{{ ipaserver_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: "{{ ipaserver_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 custodia
ipaserver_setup_custodia:
realm: "{{ result_ipaserver_test.realm }}"
hostname: "{{ result_ipaserver_test.hostname }}"
setup_ca: "{{ result_ipaserver_test.setup_ca }}"
- name: Install - Setup CA
ipaserver_setup_ca:
dm_password: "{{ ipadm_password }}"
password: "{{ ipaadmin_password }}"
master_password: "{{ ipaserver_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) }}"
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"
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
- 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: "{{ ipaserver_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
- 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
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: "{{ ipaserver_install_packages }}"
- 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 - Cleanup root IPA cache
file:
path: "/root/.ipa_cache"
state: absent
when: result_ipaserver_enable_ipa.changed
- name: Install - Configure firewalld
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
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
when: not result_ipaserver_setup_ca.csr_generated | bool
always:
- name: Cleanup temporary files
file:
path: "{{ item }}"
state: absent
with_items:
- "/etc/ipa/.tmp_pkcs12_dirsrv"
- "/etc/ipa/.tmp_pkcs12_http"
- "/etc/ipa/.tmp_pkcs12_pkinit"
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))
ansible-freeipa-v1.7.0/roles/ipaserver/tasks/main.yml 0000664 0000000 0000000 00000002213 14232747165 0022664 0 ustar 00root root 0000000 0000000 ---
# tasks file for ipaserver
- name: Import variables specific to distribution
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
include_tasks: install.yml
when: state|default('present') == 'present'
- name: Uninstall IPA server
include_tasks: uninstall.yml
when: state|default('present') == 'absent'
ansible-freeipa-v1.7.0/roles/ipaserver/tasks/uninstall.yml 0000664 0000000 0000000 00000001155 14232747165 0023755 0 ustar 00root root 0000000 0000000 ---
# tasks to uninstall IPA server
- name: Uninstall - Uninstall IPA server
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
# package:
# name: "{{ ipaserver_packages }}"
# state: absent
ansible-freeipa-v1.7.0/roles/ipaserver/vars/ 0000775 0000000 0000000 00000000000 14232747165 0021045 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/roles/ipaserver/vars/Fedora-25.yml 0000664 0000000 0000000 00000000402 14232747165 0023210 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-v1.7.0/roles/ipaserver/vars/Fedora-26.yml 0000664 0000000 0000000 00000000402 14232747165 0023211 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-v1.7.0/roles/ipaserver/vars/Fedora-27.yml 0000664 0000000 0000000 00000000402 14232747165 0023212 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-v1.7.0/roles/ipaserver/vars/Fedora.yml 0000664 0000000 0000000 00000000414 14232747165 0022767 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-v1.7.0/roles/ipaserver/vars/RedHat-7.yml 0000664 0000000 0000000 00000000401 14232747165 0023076 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-v1.7.0/roles/ipaserver/vars/RedHat-8.yml 0000664 0000000 0000000 00000000354 14232747165 0023106 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-v1.7.0/roles/ipaserver/vars/Ubuntu-18.04.yml 0000664 0000000 0000000 00000000674 14232747165 0023531 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-v1.7.0/roles/ipaserver/vars/Ubuntu.yml 0000664 0000000 0000000 00000000366 14232747165 0023057 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-v1.7.0/roles/ipaserver/vars/default.yml 0000664 0000000 0000000 00000000405 14232747165 0023213 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-v1.7.0/setup.cfg 0000664 0000000 0000000 00000004207 14232747165 0016572 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
[pylint.BASIC]
good-names =
ex, i, j, k, Run, _, e, x, dn, cn, ip, os, unicode, __metaclass__, ds
[pylint.IMPORTS]
ignored-modules =
ansible.errors, ansible.plugins.action,
ansible.module_utils, ansible.module_utils.ansible_freeipa_module,
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
[pylint.REFACTORING]
max-nested-blocks = 9
[pylint.FORMAT]
max-line-length = 80
ansible-freeipa-v1.7.0/setup.py 0000664 0000000 0000000 00000000575 14232747165 0016467 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-v1.7.0/tests/ 0000775 0000000 0000000 00000000000 14232747165 0016110 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/README.md 0000664 0000000 0000000 00000007171 14232747165 0017375 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`.
### 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[docker]>=3
```
Now you can start a test container using the following command:
```
molecule create -s centos-8
```
Note: Currently the containers available for running the tests are:
* centos-7
* centos-8
### 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=centos-8 pytest
```
### Cleaning up after tests
After running the tests you should probably destroy the test container using:
```
molecule destroy -s centos-8
```
See [Running the tests](#running-the-tests) section for more information on available options.
## 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-v1.7.0/tests/ansible.cfg 0000664 0000000 0000000 00000000537 14232747165 0020213 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-v1.7.0/tests/automember/ 0000775 0000000 0000000 00000000000 14232747165 0020250 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/automember/test_automember.yml 0000664 0000000 0000000 00000035456 14232747165 0024207 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-v1.7.0/tests/automember/test_automember_client_context.yml 0000664 0000000 0000000 00000002407 14232747165 0027277 0 ustar 00root root 0000000 0000000 ---
- name: Test automember
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_automember.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test automember using client context, in server host.
import_playbook: test_automember.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/automember/test_automember_default_group.yml 0000664 0000000 0000000 00000011755 14232747165 0027123 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-v1.7.0/tests/automember/test_automember_orphans_removed.yml 0000664 0000000 0000000 00000016607 14232747165 0027457 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
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-v1.7.0/tests/automember/test_automember_rebuilt.yml 0000664 0000000 0000000 00000011210 14232747165 0025713 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
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-v1.7.0/tests/automount/ 0000775 0000000 0000000 00000000000 14232747165 0020143 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/automount/test_automountkey.yml 0000664 0000000 0000000 00000010334 14232747165 0024472 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
- 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-v1.7.0/tests/automount/test_automountkey_client_context.yml 0000664 0000000 0000000 00000002464 14232747165 0027601 0 ustar 00root root 0000000 0000000 ---
- name: Test automountkey
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_automountkey.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test automountlocation using client context, in server host.
import_playbook: test_automountkey.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/automount/test_automountlocation.yml 0000664 0000000 0000000 00000007224 14232747165 0025516 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-v1.7.0/tests/automount/test_automountlocation_client_context.yml 0000664 0000000 0000000 00000002435 14232747165 0030617 0 ustar 00root root 0000000 0000000 ---
- name: Test automountlocation
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_automountlocation.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test automountlocation using client context, in server host.
import_playbook: test_automountlocation.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/automount/test_automountmap.yml 0000664 0000000 0000000 00000011450 14232747165 0024457 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
- 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-v1.7.0/tests/automount/test_automountmap_client_context.yml 0000664 0000000 0000000 00000002427 14232747165 0027565 0 ustar 00root root 0000000 0000000 ---
- name: Test automountmap
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_automountmap.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test automountmap using client context, in server host.
import_playbook: test_automountmap.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/azure/ 0000775 0000000 0000000 00000000000 14232747165 0017236 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/azure/azure-pipelines.yml 0000664 0000000 0000000 00000002275 14232747165 0023103 0 ustar 00root root 0000000 0000000 ---
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
stages:
# Fedora
- stage: FedoraLatest_Ansible_2_9
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: ">=2.9,<2.10"
# CentOS 9 Stream
- stage: c9s_Ansible_2_9
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: ">=2.9,<2.10"
# CentOS 8 Stream
- stage: c8s_Ansible_2_9
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: ">=2.9,<2.10"
# # CentOS 8
#
# - stage: CentOS8_Ansible_2_9
# dependsOn: []
# jobs:
# - template: templates/group_tests.yml
# parameters:
# build_number: $(Build.BuildNumber)
# scenario: centos-8
# ansible_version: ">=2.9,<2.10"
# CentOS 7
- stage: CentOS7_Ansible_2_9
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: ">=2.9,<2.10"
ansible-freeipa-v1.7.0/tests/azure/build-containers.yml 0000664 0000000 0000000 00000001700 14232747165 0023221 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'
jobs:
- template: templates/build_container.yml
parameters:
job_name_suffix: Centos7
container_name: centos-7
build_scenario_name: centos-7-build
# - template: templates/build_container.yml
# parameters:
# job_name_suffix: Centos8
# container_name: centos-8
# build_scenario_name: centos-8-build
- template: templates/build_container.yml
parameters:
job_name_suffix: C8S
container_name: c8s
build_scenario_name: c8s-build
- template: templates/build_container.yml
parameters:
job_name_suffix: C9S
container_name: c9s
build_scenario_name: c9s-build
- template: templates/build_container.yml
parameters:
job_name_suffix: FedoraLatest
container_name: fedora-latest
build_scenario_name: fedora-latest-build
ansible-freeipa-v1.7.0/tests/azure/nightly.yml 0000664 0000000 0000000 00000011036 14232747165 0021440 0 ustar 00root root 0000000 0000000 ---
schedules:
- cron: "0 19 * * *"
displayName: Nightly Builds
branches:
include:
- master
always: true
trigger: none
pool:
vmImage: 'ubuntu-latest'
stages:
# Fedora
- stage: FedoraLatest_Ansible_2_9
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: ">=2.9,<2.10"
- stage: FedoraLatest_Ansible_Core_2_11
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.11,<2.12"
- stage: FedoraLatest_Ansible_Core_2_12
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: "-core >=2.12,<2.13"
- stage: FedoraLatest_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: fedora-latest
ansible_version: ""
# CentoOS 9 Stream
- stage: c9s_Ansible_2_9
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: ">=2.9,<2.10"
- stage: c9s_Ansible_Core_2_11
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: "-core >=2.11,<2.12"
- stage: c9s_Ansible_Core_2_12
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c9s
ansible_version: "-core >=2.12,<2.13"
- 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_2_9
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: ">=2.9,<2.10"
- stage: c8s_Ansible_Core_2_11
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: "-core >=2.11,<2.12"
- stage: c8s_Ansible_Core_2_12
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: "-core >=2.12,<2.13"
- stage: c8s_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: c8s
ansible_version: ""
# # CentOS 8
#
# - stage: CentOS8_Ansible_2_9
# dependsOn: []
# jobs:
# - template: templates/group_tests.yml
# parameters:
# build_number: $(Build.BuildNumber)
# scenario: centos-8
# ansible_version: ">=2.9,<2.10"
#
# - stage: CentOS8_Ansible_Core_2_11
# dependsOn: []
# jobs:
# - template: templates/group_tests.yml
# parameters:
# build_number: $(Build.BuildNumber)
# scenario: centos-8
# ansible_version: "-core >=2.11,<2.12"
#
# - stage: CentOS8_Ansible_Core_2_12
# dependsOn: []
# jobs:
# - template: templates/group_tests.yml
# parameters:
# build_number: $(Build.BuildNumber)
# scenario: centos-8
# ansible_version: "-core >=2.12,<2.13"
#
# - stage: CentOS8_Ansible_latest
# dependsOn: []
# jobs:
# - template: templates/group_tests.yml
# parameters:
# build_number: $(Build.BuildNumber)
# scenario: centos-8
# ansible_version: ""
# CentOS 7
- stage: CentOS7_Ansible_2_9
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: ">=2.9,<2.10"
- stage: CentOS7_Ansible_Core_2_11
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: "-core >=2.11,<2.12"
- stage: CentOS7_Ansible_Core_2_12
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: "-core >=2.12,<2.13"
- stage: CentOS7_Ansible_latest
dependsOn: []
jobs:
- template: templates/group_tests.yml
parameters:
build_number: $(Build.BuildNumber)
scenario: centos-7
ansible_version: ""
ansible-freeipa-v1.7.0/tests/azure/templates/ 0000775 0000000 0000000 00000000000 14232747165 0021234 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/azure/templates/build_container.yml 0000664 0000000 0000000 00000002422 14232747165 0025120 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
displayName: Install tools
- script: pip install molecule[docker]
displayName: Install molecule
- script: molecule create -s ${{ parameters.build_scenario_name }}
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-v1.7.0/tests/azure/templates/group_tests.yml 0000664 0000000 0000000 00000002066 14232747165 0024341 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 }}
- 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 }}
- 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 }}
- template: pytest_tests.yml
parameters:
build_number: ${{ parameters.build_number }}
scenario: ${{ parameters.scenario }}
ansible_version: ${{ parameters.ansible_version }}
ansible-freeipa-v1.7.0/tests/azure/templates/playbook_tests.yml 0000664 0000000 0000000 00000004000 14232747165 0025013 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: 120
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install \
"molecule[docker]>=3" \
"ansible${{ parameters.ansible_version }}"
displayName: Install molecule and Ansible
- script: ansible-galaxy collection install community.docker ansible.posix
displayName: Install Ansible collections
- script: pip install -r requirements-tests.txt
displayName: Install dependencies
- script: |
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 }}
displayName: Setup test container
env:
ANSIBLE_LIBRARY: ./molecule
- script: |
pytest \
-m "playbook" \
--verbose \
--color=yes \
--test-group-count=${{ parameters.number_of_groups }} \
--test-group=${{ parameters.group_number }} \
--test-group-random-seed=97943259814 \
--junit-xml=TEST-results-group-${{ parameters.group_number }}.xml
displayName: Run playbook tests
env:
IPA_SERVER_HOST: ${{ parameters.scenario }}
RUN_TESTS_IN_DOCKER: true
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()
ansible-freeipa-v1.7.0/tests/azure/templates/pytest_tests.yml 0000664 0000000 0000000 00000003142 14232747165 0024531 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: 120
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '${{ parameters.python_version }}'
- script: |
pip install \
"molecule[docker]>=3" \
"ansible${{ parameters.ansible_version }}"
displayName: Install molecule and Ansible
- script: ansible-galaxy collection install community.docker ansible.posix
displayName: Install Ansible collections
- script: pip install -r requirements-tests.txt
displayName: Install dependencies
- script: |
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 }}
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
- task: PublishTestResults@2
inputs:
mergeTestResults: true
testRunTitle: PlaybookTests-Build${{ parameters.build_number }}
condition: succeededOrFailed()
ansible-freeipa-v1.7.0/tests/ca-less/ 0000775 0000000 0000000 00000000000 14232747165 0017437 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/ca-less/certificates/ 0000775 0000000 0000000 00000000000 14232747165 0022104 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/ca-less/certificates/pkinit/ 0000775 0000000 0000000 00000000000 14232747165 0023402 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/ca-less/certificates/pkinit/extensions.conf 0000664 0000000 0000000 00000001067 14232747165 0026454 0 ustar 00root root 0000000 0000000 [kdc_cert]
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}
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}
ansible-freeipa-v1.7.0/tests/ca-less/clean_up_certificates.yml 0000664 0000000 0000000 00000000524 14232747165 0024476 0 ustar 00root root 0000000 0000000 ---
- name: Clean up certificates
hosts: localhost
gather_facts: false
tasks:
- name: Run generate-certificates.sh
command: >
/bin/bash
generate-certificates.sh delete "{{ item }}"
args:
chdir: "{{ playbook_dir }}"
with_items:
- "{{ groups.ipaserver[0] }}"
- "{{ groups.ipareplicas[0] }}"
ansible-freeipa-v1.7.0/tests/ca-less/generate-certificates.sh 0000775 0000000 0000000 00000010526 14232747165 0024237 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
ROOT_CA_DIR="certificates/root-ca"
DIRSRV_CERTS_DIR="certificates/dirsrv"
HTTPD_CERTS_DIR="certificates/httpd"
PKINIT_CERTS_DIR="certificates/pkinit"
PKCS12_PASSWORD="SomePKCS12password"
# generate_ipa_pkcs12_certificate \
# $cert_name $ipa_fqdn $certs_dir $root_ca_cert $root_ca_private_key extensions_file extensions_name
function generate_ipa_pkcs12_certificate {
cert_name=$1
ipa_fqdn=$2
certs_dir=$3
root_ca_cert=$4
root_ca_private_key=$5
extensions_file=$6
extensions_name=$7
# Generate CSR and private key
openssl req -new -newkey rsa:4096 -nodes \
-subj "/C=US/ST=Test/L=Testing/O=Default/CN=${ipa_fqdn}" \
-keyout "${certs_dir}/private.key" \
-out "${certs_dir}/request.csr"
# Sign CSR to generate PEM certificate
if [ -z "${extensions_file}" ]; then
openssl x509 -req -days 365 -sha256 \
-CAcreateserial \
-CA "${root_ca_cert}" \
-CAkey "${root_ca_private_key}" \
-in "${certs_dir}/request.csr" \
-out "${certs_dir}/cert.pem"
else
openssl x509 -req -days 365 -sha256 \
-CAcreateserial \
-CA "${ROOT_CA_DIR}/cert.pem" \
-CAkey "${ROOT_CA_DIR}/private.key" \
-extfile "${extensions_file}" \
-extensions "${extensions_name}" \
-in "${certs_dir}/request.csr" \
-out "${certs_dir}/cert.pem"
fi
# Convert certificate to PKCS12 format
openssl pkcs12 -export \
-name "${cert_name}" \
-certfile "${root_ca_cert}" \
-in "${certs_dir}/cert.pem" \
-inkey "${certs_dir}/private.key" \
-passout "pass:${PKCS12_PASSWORD}" \
-out "${certs_dir}/cert.p12"
}
# generate_ipa_pkcs12_certificates $ipa_fqdn $ipa_domain
function generate_ipa_pkcs12_certificates {
host=$1
if [ -z "$host" ]; then
echo "ERROR: ipa-host-fqdn is not set"
echo
echo "usage: $0 create ipa-host-fqdn domain"
exit 0;
fi
domain=$2
if [ -z "$domain" ]; then
echo "ERROR: domain is not set"
echo
echo "usage: $0 create ipa-host-fqdn domain"
exit 0;
fi
# Generate certificates folder structure
mkdir -p "${ROOT_CA_DIR}"
mkdir -p "${DIRSRV_CERTS_DIR}/$host"
mkdir -p "${HTTPD_CERTS_DIR}/$host"
mkdir -p "${PKINIT_CERTS_DIR}/$host"
# Generate root CA
if [ ! -f "${ROOT_CA_DIR}/private.key" ]; then
openssl genrsa \
-out "${ROOT_CA_DIR}/private.key" 4096
openssl req -new -x509 -sha256 -nodes -days 3650 \
-subj "/C=US/ST=Test/L=Testing/O=Default" \
-key "${ROOT_CA_DIR}/private.key" \
-out "${ROOT_CA_DIR}/cert.pem"
fi
# Generate a certificate for the Directory Server
if [ ! -f "${DIRSRV_CERTS_DIR}/$host/cert.pem" ]; then
generate_ipa_pkcs12_certificate \
"dirsrv-cert" \
"$host" \
"${DIRSRV_CERTS_DIR}/$host" \
"${ROOT_CA_DIR}/cert.pem" \
"${ROOT_CA_DIR}/private.key"
fi
# Generate a certificate for the Apache server
if [ ! -f "${HTTPD_CERTS_DIR}/$host/cert.pem" ]; then
generate_ipa_pkcs12_certificate \
"httpd-cert" \
"$host" \
"${HTTPD_CERTS_DIR}/$host" \
"${ROOT_CA_DIR}/cert.pem" \
"${ROOT_CA_DIR}/private.key"
fi
# Generate a certificate for the KDC PKINIT
if [ ! -f "${PKINIT_CERTS_DIR}/$host/cert.pem" ]; then
export REALM=${domain^^}
generate_ipa_pkcs12_certificate \
"pkinit-cert" \
"$host" \
"${PKINIT_CERTS_DIR}/$host" \
"${ROOT_CA_DIR}/cert.pem" \
"${ROOT_CA_DIR}/private.key" \
"${PKINIT_CERTS_DIR}/extensions.conf" \
"kdc_cert"
fi
}
# delete_ipa_pkcs12_certificates $ipa_fqdn
function delete_ipa_pkcs12_certificates {
host=$1
if [ -z "$host" ]; then
echo "ERROR: ipa-host-fqdn is not set"
echo
echo "usage: $0 delete ipa-host-fqdn"
exit 0;
fi
rm -f certificates/*/"$host"/*
rm -f "${ROOT_CA_DIR}"/*
}
# Entrypoint
case "$1" in
create)
generate_ipa_pkcs12_certificates "$2" "$3"
;;
delete)
delete_ipa_pkcs12_certificates "$2"
;;
*)
echo $"Usage: $0 {create|delete}"
;;
esac
ansible-freeipa-v1.7.0/tests/ca-less/install_replica_without_ca.yml 0000664 0000000 0000000 00000004172 14232747165 0025561 0 ustar 00root root 0000000 0000000 ---
- name: Generate certificates
hosts: localhost
gather_facts: false
tasks:
- name: Run generate-certificates.sh
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"
file:
path: "/root/ca-less-test"
state: absent
- name: Generate "/root/ca-less-test"
file:
path: "/root/ca-less-test"
state: directory
mode: 0775
- name: Copy CA certificate
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
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
file:
path: /var/kerberos/krb5kdc/kdc.crt
owner: root
group: root
mode: '0644'
ansible-freeipa-v1.7.0/tests/ca-less/install_server_without_ca.yml 0000664 0000000 0000000 00000003663 14232747165 0025454 0 ustar 00root root 0000000 0000000 ---
- name: Generate certificates
hosts: localhost
gather_facts: false
tasks:
- name: Run generate-certificates.sh
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"
file:
path: "/root/ca-less-test"
state: absent
- name: Generate "/root/ca-less-test"
file:
path: "/root/ca-less-test"
state: directory
mode: 0775
- name: Copy CA certificate
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
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-v1.7.0/tests/ca-less/inventory 0000664 0000000 0000000 00000000537 14232747165 0021424 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-v1.7.0/tests/config/ 0000775 0000000 0000000 00000000000 14232747165 0017355 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/config/test_config.yml 0000664 0000000 0000000 00000050735 14232747165 0022416 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to handle server configuration
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
- include_tasks: ../env_freeipa_facts.yml
- 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.
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: ""
- block:
- name: set maxhostname to 255
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxhostname: 255
when: ipa_version is version('4.8.0', '>=')
- 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
- 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
when: ipa_version is version('4.8.0', '>=')
- 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
- block:
- name: reset maxhostname
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxhostname: '{{ previousconfig.config.maxhostname | default(omit) }}'
when: ipa_version is version('4.8.0', '>=')
- 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
- block:
- name: reset maxhostname
ipaconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
maxhostname: '{{ previousconfig.config.maxhostname | default(omit) }}'
when: ipa_version is version('4.8.0', '>=')
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."
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-v1.7.0/tests/config/test_config_client_context.yml 0000664 0000000 0000000 00000002275 14232747165 0025514 0 ustar 00root root 0000000 0000000 ---
- name: Test config
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_config.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test config using client context, in server host.
import_playbook: test_config.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/config/test_config_empty_string_params.yml 0000664 0000000 0000000 00000010570 14232747165 0026556 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-v1.7.0/tests/delegation/ 0000775 0000000 0000000 00000000000 14232747165 0020223 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/delegation/test_delegation.yml 0000664 0000000 0000000 00000023077 14232747165 0024131 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-v1.7.0/tests/delegation/test_delegation_client_context.yml 0000664 0000000 0000000 00000002363 14232747165 0027226 0 ustar 00root root 0000000 0000000 ---
- name: Test delegation
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_delegation.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test delegation using client context, in server host.
import_playbook: test_delegation.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/dnsconfig/ 0000775 0000000 0000000 00000000000 14232747165 0020062 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/dnsconfig/test_dnsconfig.yml 0000664 0000000 0000000 00000023001 14232747165 0023612 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
- ip_address: 2001:4860:4860::8888
- ip_address: 2001:4860:4860::8888
port: 53
state: absent
action: member
# Tests.
- name: Set config to 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
- ip_address: 2001:4860:4860::8888
port: 53
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
- ip_address: 2001:4860:4860::8888
port: 53
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: Ensure forwarder 8.8.4.4 is present.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.4.4
register: result
failed_when: not 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: Ensure forwarder 8.8.4.4 is present.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.4.4
register: result
failed_when: not 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.4.4
- ip_address: 8.8.8.8
register: result
failed_when: not result.changed or result.failed
- name: Ensure forwarders are absent, again.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.4.4
- ip_address: 8.8.8.8
register: result
failed_when: 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 all 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
- ip_address: 2001:4860:4860::8888
port: 53
state: absent
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure all forwarders are absent, again.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.8.8
- ip_address: 8.8.4.4
- ip_address: 2001:4860:4860::8888
port: 53
state: absent
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure forwarder 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: Ensure forwarders is not 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: Ensure forwarders are present.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.4.4
- ip_address: 8.8.8.8
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure forwarders are present, again.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.4.4
- ip_address: 8.8.8.8
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure another forwarder is present.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.4.4
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure forwarders are present.
ipadnsconfig:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
forwarders:
- ip_address: 8.8.4.4
- ip_address: 8.8.8.8
action: member
register: result
failed_when: result.changed or result.failed
# Cleanup.
- 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
- ip_address: 2001:4860:4860::8888
- ip_address: 2001:4860:4860::8888
port: 53
state: absent
action: member
ansible-freeipa-v1.7.0/tests/dnsconfig/test_dnsconfig_client_context.yml 0000664 0000000 0000000 00000002352 14232747165 0026722 0 ustar 00root root 0000000 0000000 ---
- name: Test dnsconfig
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_dnsconfig.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test dnsconfig using client context, in server host.
import_playbook: test_dnsconfig.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/dnsforwardzone/ 0000775 0000000 0000000 00000000000 14232747165 0021155 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/dnsforwardzone/test_dnsforwardzone.yml 0000664 0000000 0000000 00000027033 14232747165 0026011 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-v1.7.0/tests/dnsforwardzone/test_dnsforwardzone_client_context.yml 0000664 0000000 0000000 00000002413 14232747165 0031106 0 ustar 00root root 0000000 0000000 ---
- name: Test dnsforwardzone
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_dnsforwardzone.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test dnsforwardzone using client context, in server host.
import_playbook: test_dnsforwardzone.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/dnsrecord/ 0000775 0000000 0000000 00000000000 14232747165 0020073 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/dnsrecord/env_cleanup.yml 0000664 0000000 0000000 00000010352 14232747165 0023116 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-v1.7.0/tests/dnsrecord/env_setup.yml 0000664 0000000 0000000 00000001743 14232747165 0022633 0 ustar 00root root 0000000 0000000 ---
- name: Setup variables and facts.
include_tasks: env_vars.yml
# Cleanup before setup.
- name: Cleanup test environment.
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-v1.7.0/tests/dnsrecord/env_vars.yml 0000664 0000000 0000000 00000001512 14232747165 0022440 0 ustar 00root root 0000000 0000000 ---
# Set common vars and facts for test.
- name: Set IPv4 address prefix.
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.
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-v1.7.0/tests/dnsrecord/test_compatibility_with_ansible_module.yml 0000664 0000000 0000000 00000016606 14232747165 0030634 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-v1.7.0/tests/dnsrecord/test_dnsrecord.yml 0000664 0000000 0000000 00000147305 14232747165 0023652 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.
include_tasks: env_setup.yml
- name: Generate self-signed certificates.
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.
include_tasks: env_cleanup.yml
- name: Remove certificate files.
shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1]
become: no
delegate_to: localhost
args:
warn: no # suppres warning for not using the `file` module.
ansible-freeipa-v1.7.0/tests/dnsrecord/test_dnsrecord_client_context.yml 0000664 0000000 0000000 00000002355 14232747165 0026747 0 ustar 00root root 0000000 0000000 ---
- name: Test dnsrecord
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_dnsrecord.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test dnsrecord using client context, in server host.
import_playbook: test_dnsrecord.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/dnsrecord/test_dnsrecord_full_records.yml 0000664 0000000 0000000 00000007736 14232747165 0026420 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
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.
include_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/dnsrecord/test_dnsrecord_modify_record.yml 0000664 0000000 0000000 00000012643 14232747165 0026553 0 ustar 00root root 0000000 0000000 ---
- name: Playbook to ensure
hosts: ipaserver
become: no
gather_facts: yes
tasks:
- name: Setup testing environment.
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.
include_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/dnszone/ 0000775 0000000 0000000 00000000000 14232747165 0017570 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/dnszone/env_cleanup.yml 0000664 0000000 0000000 00000000636 14232747165 0022617 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-v1.7.0/tests/dnszone/env_setup.yml 0000664 0000000 0000000 00000000107 14232747165 0022321 0 ustar 00root root 0000000 0000000 ---
- name: Cleanup test environment.
include_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/dnszone/env_teardown.yml 0000664 0000000 0000000 00000000107 14232747165 0023004 0 ustar 00root root 0000000 0000000 ---
- name: Cleanup test environment.
include_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/dnszone/test_dnszone.yml 0000664 0000000 0000000 00000020117 14232747165 0023033 0 ustar 00root root 0000000 0000000 ---
- name: Test dnszone
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: true
tasks:
# Setup
- name: Setup testing environment
include_tasks: env_setup.yml
# Tests
- name: Check if zone is present, when in shouldn't be.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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 in shouldn't be.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
state: present
check_mode: yes
register: result
failed_when: not result.changed or result.failed
- name: Ensure zone is present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
state: present
register: result
failed_when: not result.changed or result.failed
- name: Check if zone is present, when in should be.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
state: present
check_mode: yes
register: result
failed_when: result.changed or result.failed
- name: Ensure zone is present, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
state: present
register: result
failed_when: result.changed or result.failed
- name: Ensure zone is disabled.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
state: disabled
register: result
failed_when: not result.changed or result.failed
- name: Ensure zone is disabled, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
state: disabled
register: result
failed_when: result.changed or result.failed
- name: Ensure zone is enabled.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
state: enabled
register: result
failed_when: not result.changed or result.failed
- name: Ensure zone is enabled, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
state: enabled
register: result
failed_when: result.changed or result.failed
- name: Ensure forward_policy is none.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
forward_policy: none
register: result
failed_when: not result.changed or result.failed
- name: Ensure forward_policy is none, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
forward_policy: none
register: result
failed_when: result.changed or result.failed
- name: Ensure forward_policy is first.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
forward_policy: first
register: result
failed_when: not result.changed or result.failed
- name: Ensure forward_policy is first, again.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
forward_policy: first
register: result
failed_when: result.changed or result.failed
- name: Ensure first forwarder is set.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
forwarders:
- ip_address: 2001:4860:4860::8888
register: result
failed_when: not result.changed or result.failed
- name: Nothing changes.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
register: result
failed_when: result.changed or result.failed
- name: Ensure no forwarders are set.
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: testzone.local
forwarders: []
register: result
failed_when: not result.changed or result.failed
- name: Create zones test1
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test1.testzone.local
register: result
failed_when: not result.changed or result.failed
- name: Create zones test1, again
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test1.testzone.local
register: result
failed_when: result.changed or result.failed
- name: Create zones test2
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test2.testzone.local
register: result
failed_when: not result.changed or result.failed
- name: Create zones test2, again
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test2.testzone.local
register: result
failed_when: result.changed or result.failed
- name: Create zones test3
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test3.testzone.local
register: result
failed_when: not result.changed or result.failed
- name: Create zones test3, again
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: test3.testzone.local
register: result
failed_when: result.changed or result.failed
- name: Ensure multiple zones are absent
ipadnszone:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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
include_tasks: env_teardown.yml
ansible-freeipa-v1.7.0/tests/dnszone/test_dnszone_client_context.yml 0000664 0000000 0000000 00000002341 14232747165 0026134 0 ustar 00root root 0000000 0000000 ---
- name: Test dnszone
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_dnszone.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test dnszone using client context, in server host.
import_playbook: test_dnszone.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/dnszone/test_dnszone_mod.yml 0000664 0000000 0000000 00000017036 14232747165 0023700 0 ustar 00root root 0000000 0000000 ---
- name: Test dnszone
hosts: ipaserver
become: true
gather_facts: true
tasks:
# Setup
- name: Setup testing environment
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
include_tasks: env_teardown.yml
ansible-freeipa-v1.7.0/tests/dnszone/test_dnszone_name_from_ip.yml 0000664 0000000 0000000 00000005465 14232747165 0025557 0 ustar 00root root 0000000 0000000 ---
- name: Test dnszone
hosts: ipaserver
become: yes
gather_facts: yes
tasks:
# Setup
- name: Setup testing environment
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
# - 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
include_tasks: env_teardown.yml
ansible-freeipa-v1.7.0/tests/env_freeipa_facts.yml 0000664 0000000 0000000 00000002646 14232747165 0022306 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.
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.
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.
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
- block:
- name: Get Domain from server name
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.
set_fact:
ipaserver_domain: "ipa.test"
when: "'fqdn' not in ansible_facts"
when: ipaserver_domain is not defined
ansible-freeipa-v1.7.0/tests/environment/ 0000775 0000000 0000000 00000000000 14232747165 0020454 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/environment/test_locale.yml 0000664 0000000 0000000 00000001533 14232747165 0023477 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-v1.7.0/tests/external-signed-ca-with-automatic-copy/ 0000775 0000000 0000000 00000000000 14232747165 0025467 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/external-signed-ca-with-automatic-copy/external-ca.sh 0000664 0000000 0000000 00000003411 14232747165 0030225 0 ustar 00root root 0000000 0000000 #!/bin/bash
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 00000001537 14232747165 0040172 0 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/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
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-v1.7.0/tests/external-signed-ca-with-automatic-copy/inventory 0000664 0000000 0000000 00000000254 14232747165 0027450 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-v1.7.0/tests/external-signed-ca-with-manual-copy/ 0000775 0000000 0000000 00000000000 14232747165 0024756 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/external-signed-ca-with-manual-copy/external-ca.sh 0000777 0000000 0000000 00000000000 14232747165 0042041 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 00000002260 14232747165 0036742 0 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/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' }}"
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
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
copy:
src: "{{ groups.ipaserver[0] + '-chain.crt' }}"
dest: "/root/chain.crt"
force: yes
mode: preserve
roles:
- role: ipaserver
state: present
ansible-freeipa-v1.7.0/tests/external-signed-ca-with-manual-copy/inventory 0000664 0000000 0000000 00000000254 14232747165 0026737 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-v1.7.0/tests/group/ 0000775 0000000 0000000 00000000000 14232747165 0017244 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/group/test_group.yml 0000664 0000000 0000000 00000034032 14232747165 0022164 0 ustar 00root root 0000000 0000000 ---
- name: Test group
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: true
tasks:
# setup
- include_tasks: ../env_freeipa_facts.yml
# GET FQDN_AT_DOMAIN
- name: Get fqdn_at_domain
set_fact:
fqdn_at_domain: "{{ ansible_facts['fqdn'] + '@' + ipaserver_realm }}"
# CLEANUP TEST ITEMS
- name: Ensure users user1, user2 and user3 are absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: user1,user2,user3
state: absent
- name: Ensure group group3, group2 and group1 are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group3,group2,group1
state: absent
# CREATE TEST ITEMS
- name: Ensure users user1..user3 are present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
register: result
failed_when: not result.changed or result.failed
- name: Ensure group1 is present again
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
register: result
failed_when: result.changed or result.failed
- name: Ensure group2 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group2
register: result
failed_when: not result.changed or result.failed
- name: Ensure group2 is present again
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group2
register: result
failed_when: result.changed or result.failed
- name: Ensure group3 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group3
register: result
failed_when: not result.changed or result.failed
- name: Ensure group3 is present again
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group3
register: result
failed_when: result.changed or result.failed
- name: Ensure groups group2 and group3 are present in group group1
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
group:
- group3
action: member
register: result
failed_when: result.changed or result.failed
# service
- block:
- name: Ensure service "{{ 'HTTP/' + fqdn_at_domain }}" is present in group group1
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
service:
- "{{ 'HTTP/' + fqdn_at_domain }}"
- "{{ 'ldap/' + fqdn_at_domain }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
when: ipa_version is version('4.7.0', '>=')
# user
- name: Ensure users user1, user2 and user3 are present in group group1
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
user:
- user1
- user2
- user3
action: member
register: result
failed_when: result.changed or result.failed
#- ipagroup:
# ipaadmin_password: SomeADMINpassword
# ipaapi_context: "{{ ipa_context | default(omit) }}"
# name: group1
# user:
# - user7
# action: member
- name: Ensure user user7 is absent in group group1
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
user:
- user7
action: member
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure group group4 is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group4
state: absent
register: result
failed_when: result.changed or result.failed
- name: Ensure groups group3, group2, and group1 are absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group3,group2,group1
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure group group1 is present
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
register: result
failed_when: not result.changed or result.failed
- name: Ensure users user1, user2 are present in group group1
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group1
user:
- user1
- user2
- user3
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure group group1 is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
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:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: user1,user2,user3
state: absent
register: result
failed_when: not result.changed or result.failed
ansible-freeipa-v1.7.0/tests/group/test_group_client_context.yml 0000664 0000000 0000000 00000002325 14232747165 0025266 0 ustar 00root root 0000000 0000000 ---
- name: Test group
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_group.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test group using client context, in server host.
import_playbook: test_group.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/group/test_group_external_members.yml 0000664 0000000 0000000 00000006026 14232747165 0025602 0 ustar 00root root 0000000 0000000 ---
- name: find trust
hosts: ipaserver
become: true
gather_facts: false
tasks:
- include_tasks: ../env_freeipa_facts.yml
- 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
when: trust_test_is_supported | default(false)
ansible-freeipa-v1.7.0/tests/group/test_group_external_nonposix.yml 0000664 0000000 0000000 00000021151 14232747165 0026021 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)
- 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
when: trust_test_is_supported | default(false)
# 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-v1.7.0/tests/group/test_group_idoverrideuser.yml 0000664 0000000 0000000 00000006074 14232747165 0025304 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:
- include_tasks: ../env_freeipa_facts.yml
- block:
- name: Create idoverrideuser.
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.
shell: |
kinit -c idoverride_cache admin <<< SomeADMINpassword
ipa idoverrideuser-del "Default Trust View" {{ ad_user }}
kdestroy -A -q -c idoverride_cache
when:
when: ipa_version is version("4.8.7", ">=") and trust_test_is_supported | default(false)
ansible-freeipa-v1.7.0/tests/group/test_group_membermanager.yml 0000664 0000000 0000000 00000016304 14232747165 0025050 0 ustar 00root root 0000000 0000000 ---
- name: Test group membermanagers
hosts: ipaserver
become: true
gather_facts: false
tasks:
- include_tasks: ../env_freeipa_facts.yml
- name: Tests requiring IPA 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
when: ipa_version is version('4.8.4', '>=')
ansible-freeipa-v1.7.0/tests/hbacrule/ 0000775 0000000 0000000 00000000000 14232747165 0017675 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/hbacrule/test_hbacrule.yml 0000664 0000000 0000000 00000060153 14232747165 0023251 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacrule
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
- name: Get Domain from server name
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-v1.7.0/tests/hbacrule/test_hbacrule_categories.yml 0000664 0000000 0000000 00000012415 14232747165 0025454 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-v1.7.0/tests/hbacrule/test_hbacrule_client_context.yml 0000664 0000000 0000000 00000002347 14232747165 0026354 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacrule
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_hbacrule.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test hbacrule using client context, in server host.
import_playbook: test_hbacrule.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/hbacrule/test_hbacrule_member_case_insensitive.yml 0000664 0000000 0000000 00000035732 14232747165 0030220 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:
- include_tasks: ../env_freeipa_facts.yml
- 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] }}"
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] }}"
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] }}"
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 }}"
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 }}"
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] }}"
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] }}"
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] }}"
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 }}"
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 }}"
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 }}"
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 }}"
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 }}"
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 }}"
action: member
state: absent
register: result
failed_when: result.changed or result.failed
always:
- name: Ensure test hbacrule is absent
ipahbacrule:
ipaadmin_password: SomeADMINpassword
name: testrule
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-v1.7.0/tests/hbacrule/test_hbacrule_member_empty.yml 0000664 0000000 0000000 00000024170 14232747165 0026015 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacrule
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- 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-v1.7.0/tests/hbacsvc/ 0000775 0000000 0000000 00000000000 14232747165 0017521 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/hbacsvc/test_hbacsvc.yml 0000664 0000000 0000000 00000003754 14232747165 0022725 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-v1.7.0/tests/hbacsvc/test_hbacsvc_client_context.yml 0000664 0000000 0000000 00000002341 14232747165 0026016 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacsvc
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_hbacsvc.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test hbacsvc using client context, in server host.
import_playbook: test_hbacsvc.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/hbacsvcgroup/ 0000775 0000000 0000000 00000000000 14232747165 0020576 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/hbacsvcgroup/test_hbacsvcgroup.yml 0000664 0000000 0000000 00000006011 14232747165 0025044 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-v1.7.0/tests/hbacsvcgroup/test_hbacsvcgroup_client_context.yml 0000664 0000000 0000000 00000002377 14232747165 0030161 0 ustar 00root root 0000000 0000000 ---
- name: Test hbacsvcgroup
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_hbacsvcgroup.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test hbacsvcgroup using client context, in server host.
import_playbook: test_hbacsvcgroup.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/hbacsvcgroup/test_hbacsvcgroup_member_case_insensitive.yml 0000664 0000000 0000000 00000016701 14232747165 0032015 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:
- 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-v1.7.0/tests/host/ 0000775 0000000 0000000 00000000000 14232747165 0017065 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/host/certificate/ 0000775 0000000 0000000 00000000000 14232747165 0021347 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/host/certificate/test_host_certificate.yml 0000664 0000000 0000000 00000007020 14232747165 0026447 0 ustar 00root root 0000000 0000000 ---
- name: Test host certificates
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Generate self-signed certificates.
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.
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
args:
warn: no # suppres warning for not using the `file` module.
ansible-freeipa-v1.7.0/tests/host/certificate/test_hosts_certificate.yml 0000664 0000000 0000000 00000006640 14232747165 0026641 0 ustar 00root root 0000000 0000000 ---
- name: Test host certificates
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
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.
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.
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
args:
warn: no # suppres warning for not using the `file` module.
ansible-freeipa-v1.7.0/tests/host/test_host.yml 0000664 0000000 0000000 00000016113 14232747165 0021626 0 ustar 00root root 0000000 0000000 ---
- name: Test host
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host6_fqdn
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: Get IPv4 address prefix from server node
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-v1.7.0/tests/host/test_host_allow_create_keytab.yml 0000664 0000000 0000000 00000016636 14232747165 0025720 0 ustar 00root root 0000000 0000000 ---
- name: Test host allow_create_keytab
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Get Realm from server name
set_fact:
ipaserver_realm: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') | upper }}"
when: ipaserver_realm is not defined
- name: Set host1_fqdn .. host3_fqdn
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-v1.7.0/tests/host/test_host_allow_retrieve_keytab.yml 0000664 0000000 0000000 00000016734 14232747165 0026301 0 ustar 00root root 0000000 0000000 ---
- name: Test host allow_retrieve_keytab
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Get Realm from server name
set_fact:
ipaserver_realm: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') | upper }}"
when: ipaserver_realm is not defined
- name: Set host1_fqdn .. host3_fqdn
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-v1.7.0/tests/host/test_host_bool_params.yml 0000664 0000000 0000000 00000007173 14232747165 0024212 0 ustar 00root root 0000000 0000000 ---
- name: Test host bool parameters
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host6_fqdn
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-v1.7.0/tests/host/test_host_client_context.yml 0000664 0000000 0000000 00000002333 14232747165 0024727 0 ustar 00root root 0000000 0000000 ---
- name: Test host
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_host.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test automember using client context, in server host.
import_playbook: test_host.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/host/test_host_empty_string_params.yml 0000664 0000000 0000000 00000004710 14232747165 0025775 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
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host6_fqdn
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-v1.7.0/tests/host/test_host_ipaddresses.yml 0000664 0000000 0000000 00000023174 14232747165 0024221 0 ustar 00root root 0000000 0000000 ---
- name: Test host IP addresses
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host6_fqdn
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
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-v1.7.0/tests/host/test_host_managedby_host.yml 0000664 0000000 0000000 00000007367 14232747165 0024705 0 ustar 00root root 0000000 0000000 ---
- name: Test host managedby_host
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host2_fqdn
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-v1.7.0/tests/host/test_host_no_zone.yml 0000664 0000000 0000000 00000000454 14232747165 0023356 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-v1.7.0/tests/host/test_host_principal.yml 0000664 0000000 0000000 00000010370 14232747165 0023666 0 ustar 00root root 0000000 0000000 ---
- name: Test host principal
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Get Realm from server name
set_fact:
ipaserver_realm: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') | upper }}"
when: ipaserver_realm is not defined
- name: Set host1_fqdn
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-v1.7.0/tests/host/test_host_random.yml 0000664 0000000 0000000 00000005732 14232747165 0023173 0 ustar 00root root 0000000 0000000 ---
- name: Test ipahost random password generation
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn and host2_fqdn
set_fact:
host1_fqdn: "{{ 'host1.' + ipaserver_domain }}"
host2_fqdn: "{{ 'host2.' + ipaserver_domain }}"
- 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.
assert:
that:
- ipahost.host.randompassword is defined
- name: Print generated random password
debug:
var: ipahost.host.randompassword
- 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.
assert:
that:
- ipahost.host["{{ host1_fqdn }}"].randompassword is
defined
- ipahost.host["{{ host2_fqdn }}"].randompassword is
defined
- name: Print generated random password for "{{ host1_fqdn }}"
debug:
var: ipahost.host["{{ host1_fqdn }}"].randompassword
- name: Print generated random password for "{{ host2_fqdn }}"
debug:
var: ipahost.host["{{ host2_fqdn }}"].randompassword
- name: Enrolled host "{{ ansible_facts['fqdn'] }}" fails to set random password with update_password always
ipahost:
ipaadmin_password: SomeADMINpassword
hosts:
- name: "{{ ansible_facts['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'.
assert:
that:
- ipahost.host["{{ ansible_facts['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-v1.7.0/tests/host/test_host_reverse.yml 0000664 0000000 0000000 00000007031 14232747165 0023360 0 ustar 00root root 0000000 0000000 ---
- name: Test host
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn
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
set_fact:
ipv4_prefix: "{{ ansible_facts['default_ipv4'].address.split('.')[:-1] |
join('.') }}"
- name: Set zone prefixes.
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-v1.7.0/tests/host/test_hosts.yml 0000664 0000000 0000000 00000006341 14232747165 0022013 0 ustar 00root root 0000000 0000000 ---
- name: Test hosts
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host6_fqdn
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-v1.7.0/tests/host/test_hosts_managedby_host.yml 0000664 0000000 0000000 00000011647 14232747165 0025064 0 ustar 00root root 0000000 0000000 ---
- name: Test hosts managedby_host
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Set host1_fqdn .. host5_fqdn
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-v1.7.0/tests/host/test_hosts_principal.yml 0000664 0000000 0000000 00000014204 14232747165 0024051 0 ustar 00root root 0000000 0000000 ---
- name: Test hosts principal
hosts: ipaserver
become: true
tasks:
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Get Realm from server name
set_fact:
ipaserver_realm: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') | upper }}"
when: ipaserver_realm is not defined
- name: Set host1_fqdn .. host2_fqdn
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-v1.7.0/tests/hostgroup/ 0000775 0000000 0000000 00000000000 14232747165 0020142 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/hostgroup/test_hostgroup.yml 0000664 0000000 0000000 00000015022 14232747165 0023756 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
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-v1.7.0/tests/hostgroup/test_hostgroup_client_context.yml 0000664 0000000 0000000 00000002355 14232747165 0027065 0 ustar 00root root 0000000 0000000 ---
- name: Test hostgroup
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_hostgroup.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test hostgroup using client context, in server host.
import_playbook: test_hostgroup.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/hostgroup/test_hostgroup_membermanager.yml 0000664 0000000 0000000 00000017476 14232747165 0026657 0 ustar 00root root 0000000 0000000 ---
- name: Test hostgroup membermanagers
hosts: ipaserver
become: true
gather_facts: false
tasks:
- include_tasks: ../env_freeipa_facts.yml
- name: Tests requiring IPA 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
when: ipa_version is version('4.8.4', '>=')
ansible-freeipa-v1.7.0/tests/hostgroup/test_hostgroup_rename.yml 0000664 0000000 0000000 00000006553 14232747165 0025316 0 ustar 00root root 0000000 0000000 ---
- name: Test hostgroup
hosts: ipaserver
become: true
gather_facts: false
tasks:
- include_tasks: ../env_freeipa_facts.yml
- name: Tests requiring IPA 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
when: ipa_version is version('4.8.7', '>=')
ansible-freeipa-v1.7.0/tests/idrange/ 0000775 0000000 0000000 00000000000 14232747165 0017521 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/idrange/tasks_remove_trust.yml 0000664 0000000 0000000 00000001304 14232747165 0024205 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-v1.7.0/tests/idrange/tasks_set_trust.yml 0000664 0000000 0000000 00000002270 14232747165 0023506 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
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.
set_fact:
ipa_domain_sid: "{{ getsid.stdout }}"
ansible-freeipa-v1.7.0/tests/idrange/test_idrange.yml 0000664 0000000 0000000 00000023006 14232747165 0022715 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.
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.
- 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
- block:
# Create trust with range_type: ipa-ad-trust-posix
- name: Create trust with range_type 'ipa-ad-trust'
include_tasks: tasks_set_trust.yml
vars:
trust_base_id: 10000000
trust_range_size: 200000
trust_range_type: ipa-ad-trust
# Can't user 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.
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'
include_tasks: tasks_set_trust.yml
vars:
trust_base_id: 10000000
trust_range_size: 2000000
trust_range_type: ipa-ad-trust-posix
# Can't user 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
always:
# CLEANUP TEST ITEMS
- name: Remove test trust.
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
when: trust_test_is_supported | default(false)
ansible-freeipa-v1.7.0/tests/idrange/test_idrange_client_context.yml 0000664 0000000 0000000 00000002430 14232747165 0026015 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.
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.
import_playbook: test_idrange.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test idrange using client context, in server host.
import_playbook: test_idrange.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
ansible-freeipa-v1.7.0/tests/location/ 0000775 0000000 0000000 00000000000 14232747165 0017720 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/location/test_location.yml 0000664 0000000 0000000 00000004475 14232747165 0023324 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-v1.7.0/tests/location/test_location_client_context.yml 0000664 0000000 0000000 00000002347 14232747165 0026422 0 ustar 00root root 0000000 0000000 ---
- name: Test location
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_location.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test location using client context, in server host.
import_playbook: test_location.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/permission/ 0000775 0000000 0000000 00000000000 14232747165 0020300 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/permission/test_permission.yml 0000664 0000000 0000000 00000031300 14232747165 0024247 0 ustar 00root root 0000000 0000000 ---
- name: Test permission
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
tasks:
- 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-v1.7.0/tests/permission/test_permission_client_context.yml 0000664 0000000 0000000 00000002363 14232747165 0027360 0 ustar 00root root 0000000 0000000 ---
- name: Test permission
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_permission.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test permission using client context, in server host.
import_playbook: test_permission.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/privilege/ 0000775 0000000 0000000 00000000000 14232747165 0020076 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/privilege/test_privilege.yml 0000664 0000000 0000000 00000017457 14232747165 0023664 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-v1.7.0/tests/privilege/test_privilege_client_context.yml 0000664 0000000 0000000 00000002355 14232747165 0026755 0 ustar 00root root 0000000 0000000 ---
- name: Test privilege
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_privilege.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test privilege using client context, in server host.
import_playbook: test_privilege.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/pwpolicy/ 0000775 0000000 0000000 00000000000 14232747165 0017756 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/pwpolicy/test_pwpolicy.yml 0000664 0000000 0000000 00000006664 14232747165 0023422 0 ustar 00root root 0000000 0000000 ---
- name: Test pwpolicy
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: false
tasks:
- 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
ansible-freeipa-v1.7.0/tests/pwpolicy/test_pwpolicy_client_context.yml 0000664 0000000 0000000 00000002347 14232747165 0026516 0 ustar 00root root 0000000 0000000 ---
- name: Test pwpolicy
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_pwpolicy.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test pwpolicy using client context, in server host.
import_playbook: test_pwpolicy.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/pytests/ 0000775 0000000 0000000 00000000000 14232747165 0017623 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/pytests/conftest.py 0000664 0000000 0000000 00000003431 14232747165 0022023 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):
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.yaml")
inventory = get_inventory(inventory_path)
print("Configuring execution using {}".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-v1.7.0/tests/pytests/dnszone/ 0000775 0000000 0000000 00000000000 14232747165 0021303 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/pytests/dnszone/playbooks/ 0000775 0000000 0000000 00000000000 14232747165 0023306 5 ustar 00root root 0000000 0000000 dnszone_add_multiple_ipv4_ipv6_forwarders.yaml 0000664 0000000 0000000 00000000750 14232747165 0034464 0 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/pytests/dnszone/playbooks ---
- 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-v1.7.0/tests/pytests/dnszone/playbooks/dnszone_add_without_forwarder.yaml 0000664 0000000 0000000 00000000424 14232747165 0032320 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-v1.7.0/tests/pytests/dnszone/playbooks/dnszone_del_multiple.yaml 0000664 0000000 0000000 00000000417 14232747165 0030413 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-v1.7.0/tests/pytests/dnszone/playbooks/dnszone_disable.yaml 0000664 0000000 0000000 00000000347 14232747165 0027341 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-v1.7.0/tests/pytests/dnszone/playbooks/dnszone_enable.yaml 0000664 0000000 0000000 00000000344 14232747165 0027161 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-v1.7.0/tests/pytests/dnszone/playbooks/dnszone_invalid_ip.yaml 0000664 0000000 0000000 00000000456 14232747165 0030055 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-v1.7.0/tests/pytests/dnszone/playbooks/dnszone_invalid_serial.yaml 0000664 0000000 0000000 00000000473 14232747165 0030723 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-v1.7.0/tests/pytests/dnszone/playbooks/dnszone_name_from_ip.yaml 0000664 0000000 0000000 00000000404 14232747165 0030363 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-v1.7.0/tests/pytests/dnszone/playbooks/dnszone_with_forward_policy_only.yaml 0000664 0000000 0000000 00000000441 14232747165 0033050 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-v1.7.0/tests/pytests/dnszone/test_dnszone.py 0000664 0000000 0000000 00000012112 14232747165 0024371 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.yaml")
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.yaml")
)
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.yaml")
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"], "dnszone-find", [zone26])
# Disable dns zone
self.run_playbook(BASE_PATH + "dnszone_disable.yaml")
self.check_details(["Active zone: FALSE"], "dnszone-find", [zone26])
def test_dnszone_enable(self):
"""TC-31: Enable DNS Zone."""
zone26 = "26testzone.test"
self.check_details(["Active zone: FALSE"], "dnszone-find", [zone26])
# Enable dns zone
self.run_playbook(BASE_PATH + "dnszone_enable.yaml")
self.check_details(["Active zone: 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.yaml")
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.yaml")
# 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.yaml", expected_error,
)
self.check_notexists(
[invalid_zone_ip], "dnszone-show", [invalid_zone_name],
)
ansible-freeipa-v1.7.0/tests/role/ 0000775 0000000 0000000 00000000000 14232747165 0017051 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/role/env_cleanup.yml 0000664 0000000 0000000 00000002444 14232747165 0022077 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-v1.7.0/tests/role/env_facts.yml 0000664 0000000 0000000 00000001216 14232747165 0021544 0 ustar 00root root 0000000 0000000 ---
- block:
- name: Get Domain from server name
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.
set_fact:
ipaserver_domain: "ipa.test"
when: "'fqdn' not in ansible_facts"
when: ipaserver_domain is not defined
- name: Set ipaserver_realm.
set_fact:
ipaserver_realm: "{{ ipaserver_domain | upper }}"
when: ipaserver_realm is not defined
- name: Create FQDN for host01
set_fact:
host1_fqdn: "host01.{{ ipaserver_domain }}"
host2_fqdn: "host02.{{ ipaserver_domain }}"
ansible-freeipa-v1.7.0/tests/role/env_setup.yml 0000664 0000000 0000000 00000002611 14232747165 0021604 0 ustar 00root root 0000000 0000000 ---
- name: Cleanup environment.
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-v1.7.0/tests/role/test_role.yml 0000664 0000000 0000000 00000027423 14232747165 0021604 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.
import_tasks: env_facts.yml
- name: Setup environment.
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.
include_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/role/test_role_client_context.yml 0000664 0000000 0000000 00000002317 14232747165 0024701 0 ustar 00root root 0000000 0000000 ---
- name: Test role
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_role.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test role using client context, in server host.
import_playbook: test_role.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/role/test_role_lists_handling.yml 0000664 0000000 0000000 00000016504 14232747165 0024664 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.
import_tasks: env_facts.yml
- name: Setup environment.
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.
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.
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.
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.
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.
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.
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.
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.
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.
include_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/role/test_role_member_case_insensitive.yml 0000664 0000000 0000000 00000032664 14232747165 0026551 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:
- include_tasks: ../env_freeipa_facts.yml
- 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-v1.7.0/tests/role/test_role_service_member.yml 0000664 0000000 0000000 00000004675 14232747165 0024657 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.
import_tasks: env_facts.yml
- name: Setup environment.
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.
include_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/sanity/ 0000775 0000000 0000000 00000000000 14232747165 0017417 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/sanity/galaxy-importer.cfg 0000664 0000000 0000000 00000000174 14232747165 0023226 0 ustar 00root root 0000000 0000000 [galaxy-importer]
RUN_ANSIBLE_TEST = True
RUN_ANSIBLE_LINT = True
ANSIBLE_TEST_LOCAL_IMAGE = True
LOCAL_IMAGE_DOCKER = True
ansible-freeipa-v1.7.0/tests/sanity/ignore-2.12.txt 0000664 0000000 0000000 00000006757 14232747165 0022042 0 ustar 00root root 0000000 0000000 plugins/module_utils/ansible_freeipa_module.py compile-2.6!skip
plugins/module_utils/ansible_freeipa_module.py import-2.6!skip
plugins/module_utils/ansible_freeipa_module.py pylint:ansible-bad-import-from
plugins/module_utils/ansible_freeipa_module.py pylint:ansible-bad-function
plugins/module_utils/ansible_freeipa_module.py pylint:ansible-format-automatic-specification
plugins/module_utils/ansible_freeipa_module.py pylint:ansible-deprecated-no-collection-name
plugins/modules/ipaclient_get_facts.py compile-2.6!skip
plugins/modules/ipaclient_get_facts.py import-2.6!skip
plugins/modules/ipaclient_api.py pylint:ansible-format-automatic-specification
plugins/modules/ipaclient_join.py pylint:ansible-format-automatic-specification
plugins/modules/ipaclient_test.py pylint:ansible-format-automatic-specification
plugins/modules/ipaconfig.py compile-2.6!skip
plugins/modules/ipaconfig.py import-2.6!skip
plugins/modules/ipadnsrecord.py compile-2.6!skip
plugins/modules/ipadnsrecord.py import-2.6!skip
plugins/modules/ipadnsrecord.py pylint:ansible-format-automatic-specification
plugins/modules/ipadnsrecord.py pylint:use-maxsplit-arg
plugins/modules/ipareplica_enable_ipa.py pylint:ansible-format-automatic-specification
plugins/modules/ipareplica_prepare.py pylint:ansible-format-automatic-specification
plugins/modules/ipareplica_test.py pylint:ansible-format-automatic-specification
plugins/modules/iparole.py compile-2.6!skip
plugins/modules/iparole.py import-2.6!skip
plugins/modules/ipaserver_setup_ca.py compile-2.6!skip
plugins/modules/ipaserver_setup_ca.py import-2.6!skip
plugins/modules/ipaserver_test.py pylint:ansible-format-automatic-specification
plugins/modules/ipaservice.py compile-2.6!skip
plugins/modules/ipaservice.py import-2.6!skip
plugins/modules/ipasudorule.py compile-2.6!skip
plugins/modules/ipasudorule.py import-2.6!skip
plugins/modules/ipavault.py compile-2.6!skip
plugins/modules/ipavault.py import-2.6!skip
roles/ipaclient/library/ipaclient_api.py pylint:ansible-format-automatic-specification
roles/ipaclient/library/ipaclient_join.py pylint:ansible-format-automatic-specification
roles/ipaclient/library/ipaclient_test.py pylint:ansible-format-automatic-specification
roles/ipareplica/library/ipareplica_enable_ipa.py pylint:ansible-format-automatic-specification
roles/ipareplica/library/ipareplica_prepare.py pylint:ansible-format-automatic-specification
roles/ipareplica/library/ipareplica_test.py pylint:ansible-format-automatic-specification
roles/ipaserver/library/ipaserver_test.py pylint:ansible-format-automatic-specification
roles/ipareplica/module_utils/ansible_ipa_replica.py pylint:ansible-format-automatic-specification
tests/external-signed-ca-with-automatic-copy/external-ca.sh shebang!skip
tests/pytests/conftest.py pylint:ansible-format-automatic-specification
tests/sanity/sanity.sh shebang!skip
tests/user/users.sh shebang!skip
tests/user/users_absent.sh shebang!skip
tests/utils.py pylint:ansible-format-automatic-specification
tests/utils.py pylint:subprocess-run-check
utils/ansible-doc-test shebang!skip
utils/ansible-ipa-client-install shebang!skip
utils/ansible-ipa-replica-install shebang!skip
utils/ansible-ipa-server-install shebang!skip
utils/build-galaxy-release.sh shebang!skip
utils/build-srpm.sh shebang!skip
utils/changelog shebang!skip
utils/galaxyfy-README.py shebang!skip
utils/galaxyfy-module-EXAMPLES.py shebang!skip
utils/galaxyfy-playbook.py shebang!skip
utils/galaxyfy.py shebang!skip
utils/gen_modules_docs.sh shebang!skip
utils/lint_check.sh shebang!skip
utils/new_module shebang!skip
ansible-freeipa-v1.7.0/tests/sanity/sanity.sh 0000664 0000000 0000000 00000001355 14232747165 0021266 0 ustar 00root root 0000000 0000000 #!/bin/bash
VENV=/tmp/ansible-test-venv
ANSIBLE_COLLECTION=freeipa-ansible_freeipa
virtualenv "$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
export GALAXY_IMPORTER_CONFIG=tests/sanity/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"
exit "$error"
ansible-freeipa-v1.7.0/tests/selfservice/ 0000775 0000000 0000000 00000000000 14232747165 0020422 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/selfservice/test_selfservice.yml 0000664 0000000 0000000 00000014276 14232747165 0024530 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-v1.7.0/tests/selfservice/test_selfservice_client_context.yml 0000664 0000000 0000000 00000002371 14232747165 0027623 0 ustar 00root root 0000000 0000000 ---
- name: Test selfservice
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_selfservice.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test selfservice using client context, in server host.
import_playbook: test_selfservice.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/server/ 0000775 0000000 0000000 00000000000 14232747165 0017416 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/server/test_server.yml 0000664 0000000 0000000 00000013657 14232747165 0022522 0 ustar 00root root 0000000 0000000 ---
- name: Test server
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: yes
tasks:
# CLEANUP TEST ITEMS
- block:
- name: Get server name from hostname
set_fact:
ipa_server_name: "{{ ansible_facts['hostname'].split('.')[0] }}"
rescue:
- name: Fallback to 'ipaserver'
set_fact:
ipa_server_name: ipaserver
when: ipa_server_name is not defined
- block:
- name: Get domain name from hostname.
set_fact:
ipaserver_domain: "{{ ansible_facts['hostname'].split('.')[0][1:] }}"
rescue:
- name: Fallback to 'ipa.test'
set_fact:
ipaserver_domain: "ipa.test"
when: ipaserver_domain is not defined
- 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-v1.7.0/tests/server/test_server_client_context.yml 0000664 0000000 0000000 00000002333 14232747165 0025611 0 ustar 00root root 0000000 0000000 ---
- name: Test server
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_server.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test server using client context, in server host.
import_playbook: test_server.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/service/ 0000775 0000000 0000000 00000000000 14232747165 0017550 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/service/certificate/ 0000775 0000000 0000000 00000000000 14232747165 0022032 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/service/certificate/test_service_certificate.yml 0000664 0000000 0000000 00000014461 14232747165 0027624 0 ustar 00root root 0000000 0000000 ---
- name: Test service certificates
hosts: ipaserver
become: true
tasks:
# setup
- name: Generate self-signed certificates.
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
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Get IPv4 address prefix from server node
set_fact:
ipv4_prefix: "{{ ansible_facts['default_ipv4'].address.split('.')[:-1] |
join('.') }}"
- name: Set test host FQDN
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.
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
args:
warn: no # suppres warning for not using the `file` module.
ansible-freeipa-v1.7.0/tests/service/env_cleanup.yml 0000664 0000000 0000000 00000003770 14232747165 0022601 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-v1.7.0/tests/service/env_setup.yml 0000664 0000000 0000000 00000004041 14232747165 0022302 0 ustar 00root root 0000000 0000000 # Setup environment for service module tests.
---
- name: Setup variables and facts.
include_tasks: env_vars.yml
# Cleanup before setup.
- name: Cleanup test environment.
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-v1.7.0/tests/service/env_vars.yml 0000664 0000000 0000000 00000001072 14232747165 0022116 0 ustar 00root root 0000000 0000000 ---
- name: Get Domain from server name
set_fact:
test_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
- name: Set host1, host2 and svc hosts fqdn
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
set_fact:
ipv4_prefix: "{{ ansible_facts['default_ipv4'].address.split('.')[:-1] | join('.') }}"
ansible-freeipa-v1.7.0/tests/service/test_service.yml 0000664 0000000 0000000 00000047010 14232747165 0022774 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
- include_tasks: ../env_freeipa_facts.yml
# tests
- name: Tests with skip_host_check, require IPA version 4.8.0+.
block:
- name: Setup test environment
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
include_tasks: env_cleanup.yml
when: ipa_version is version('4.7.0', '>=')
ansible-freeipa-v1.7.0/tests/service/test_service_client_context.yml 0000664 0000000 0000000 00000002341 14232747165 0026074 0 ustar 00root root 0000000 0000000 ---
- name: Test service
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_service.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test service using client context, in server host.
import_playbook: test_service.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/service/test_service_disable.yml 0000664 0000000 0000000 00000007263 14232747165 0024465 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`.
shell: echo SomeADMINpassword | kinit -c ${KRB5CCNAME} admin
- name: Generate self-signed certificates.
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
shell: ipa-getkeytab -s "{{ ansible_facts['fqdn'] }}" -p "mysvc1/{{ ansible_facts['fqdn'] }}" -k mysvc1.keytab
- name: Verify keytab
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
shell: ipa service-find "mysvc1/{{ ansible_facts['fqdn'] }}"
register: result
failed_when: result.failed or result.stdout | regex_search(" Keytab. true")
- name: Obtain keytab
shell: ipa-getkeytab -s "{{ ansible_facts['fqdn'] }}" -p "mysvc1/{{ ansible_facts['fqdn'] }}" -k mysvc1.keytab
- name: Verify keytab
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
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.
shell: kdestroy -A -q -c ${KRB5CCNAME}
- name: Remove certificate files.
shell:
cmd: rm -f "private{{ item }}.key" "cert{{ item }}.pem" "cert{{ item }}.der" "cert{{ item }}.b64"
with_items: [1]
become: no
delegate_to: localhost
args:
warn: no # suppres warning for not using the `file` module.
ansible-freeipa-v1.7.0/tests/service/test_service_empty_string_params.yml 0000664 0000000 0000000 00000007131 14232747165 0027143 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-v1.7.0/tests/service/test_service_keytab.yml 0000664 0000000 0000000 00000027641 14232747165 0024343 0 ustar 00root root 0000000 0000000 ---
- name: Test service
hosts: ipaserver
become: yes
tasks:
# setup
- name: Setup test envirnoment.
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.
include_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/service/test_service_without_skip_host_check.yml 0000664 0000000 0000000 00000032576 14232747165 0030012 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
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
include_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/servicedelegationrule/ 0000775 0000000 0000000 00000000000 14232747165 0022474 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/servicedelegationrule/test_servicedelegationrule.yml 0000664 0000000 0000000 00000017614 14232747165 0030653 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-v1.7.0/tests/servicedelegationrule/test_servicedelegationrule_client_context.yml 0000664 0000000 0000000 00000002554 14232747165 0033752 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.
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.
import_playbook: test_servicedelegationrule.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test servicedelegationrule using client context, in server host.
import_playbook: test_servicedelegationrule.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
ansible-freeipa-v1.7.0/tests/servicedelegationrule/test_servicedelegationrule_hostprincipal.yml 0000664 0000000 0000000 00000012346 14232747165 0033607 0 ustar 00root root 0000000 0000000 ---
- name: Test servicedelegationrule_hostprincipal
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: yes
tasks:
# setup
- include_tasks: ../env_freeipa_facts.yml
# host principals are only possible with IPA 4.9.0+
- block:
# SET FACTS
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Get REALM from server name
set_fact:
ipaserver_realm: "{{ ipaserver_domain | upper }}"
when: ipaserver_realm is not defined
- name: Set test-host fqdn
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
when: ipa_version is version('4.9.0', '>=')
ansible-freeipa-v1.7.0/tests/servicedelegationtarget/ 0000775 0000000 0000000 00000000000 14232747165 0023013 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/servicedelegationtarget/test_servicedelegationtarget.yml 0000664 0000000 0000000 00000027653 14232747165 0031515 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-v1.7.0/tests/servicedelegationtarget/test_servicedelegationtarget_client_context.yml0000664 0000000 0000000 00000002570 14232747165 0034606 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.
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.
import_playbook: test_servicedelegationtarget.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test servicedelegationtarget using client context, in server host.
import_playbook: test_servicedelegationtarget.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
ansible-freeipa-v1.7.0/tests/servicedelegationtarget/test_servicedelegationtarget_hostprincipal.yml 0000664 0000000 0000000 00000012460 14232747165 0034442 0 ustar 00root root 0000000 0000000 ---
- name: Test servicedelegationtarget_hostprincipal
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: yes
tasks:
# setup
- include_tasks: ../env_freeipa_facts.yml
# host principals are only possible with IPA 4.9.0+
- block:
# SET FACTS
- name: Get Domain from server name
set_fact:
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join ('.') }}"
when: ipaserver_domain is not defined
- name: Get REALM from server name
set_fact:
ipaserver_realm: "{{ ipaserver_domain | upper }}"
when: ipaserver_realm is not defined
- name: Set test-host fqdn
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
when: ipa_version is version('4.9.0', '>=')
ansible-freeipa-v1.7.0/tests/sudocmd/ 0000775 0000000 0000000 00000000000 14232747165 0017546 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/sudocmd/test_sudocmd.yml 0000664 0000000 0000000 00000007333 14232747165 0022774 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-v1.7.0/tests/sudocmd/test_sudocmd_client_context.yml 0000664 0000000 0000000 00000002341 14232747165 0026070 0 ustar 00root root 0000000 0000000 ---
- name: Test sudocmd
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_sudocmd.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test sudocmd using client context, in server host.
import_playbook: test_sudocmd.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/sudocmdgroup/ 0000775 0000000 0000000 00000000000 14232747165 0020623 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/sudocmdgroup/test_sudocmdgroup.yml 0000664 0000000 0000000 00000015663 14232747165 0025133 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
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-v1.7.0/tests/sudocmdgroup/test_sudocmdgroup_client_context.yml 0000664 0000000 0000000 00000002377 14232747165 0030233 0 ustar 00root root 0000000 0000000 ---
- name: Test sudocmdgroup
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_sudocmdgroup.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test sudocmdgroup using client context, in server host.
import_playbook: test_sudocmdgroup.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/sudorule/ 0000775 0000000 0000000 00000000000 14232747165 0017752 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/sudorule/test_sudorule.yml 0000664 0000000 0000000 00000077701 14232747165 0023412 0 ustar 00root root 0000000 0000000 ---
- name: Test sudorule
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true
gather_facts: true
tasks:
# setup
- name: Ensure user is absent
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: user01
state: absent
- name: Ensure group is absent
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group01
state: absent
- name: Ensure user is present
ipauser:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: user01
first: user
last: zeroone
- name: Ensure group is present, with user01 on it.
ipagroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: group01
user: user01
- 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
- 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 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
# cleanup
- name: Ensure sudocmdgroup is absent
ipasudocmdgroup:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name:
- test_sudorule
- test_sudorule2
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
ansible-freeipa-v1.7.0/tests/sudorule/test_sudorule_categories.yml 0000664 0000000 0000000 00000017367 14232747165 0025621 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
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-v1.7.0/tests/sudorule/test_sudorule_client_context.yml 0000664 0000000 0000000 00000002347 14232747165 0026506 0 ustar 00root root 0000000 0000000 ---
- name: Test sudorule
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_sudorule.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test sudorule using client context, in server host.
import_playbook: test_sudorule.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/sudorule/test_sudorule_member_case_insensitive.yml 0000664 0000000 0000000 00000021002 14232747165 0030333 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:
- block:
# SETUP
- name: Ensure domain name
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.
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.
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-v1.7.0/tests/sudorule/test_sudorule_single_hostnames.yml 0000664 0000000 0000000 00000010756 14232747165 0027031 0 ustar 00root root 0000000 0000000 ---
- name: Test sudorule with single hostnames.
hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: no
gather_facts: no
tasks:
- block:
# setup test environment
- name: Get Domain from the server name
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-v1.7.0/tests/test_playbook_runs.py 0000664 0000000 0000000 00000004256 14232747165 0022417 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
def prepare_test(test_name, test_path):
"""Decorator for the 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"] = test_path
kwargs["test_name"] = test_name
return func(*args, **kwargs)
return wrapper
decorator.__name__ = test_name
return decorator
# 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"]
@pytest.mark.skipif(
not get_server_host(),
reason="Environment variable IPA_SERVER_HOST must be set",
)
@pytest.mark.playbook
@prepare_test(test_name, test_path)
def method(self, test_path, test_name):
run_playbook(test_path)
_tests[test_name] = method
globals()[test_dir_name] = type(test_dir_name, tuple([TestCase]), _tests,)
ansible-freeipa-v1.7.0/tests/trust/ 0000775 0000000 0000000 00000000000 14232747165 0017271 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/trust/test_trust.yml 0000664 0000000 0000000 00000013525 14232747165 0022242 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:
- block:
- name: Delete test trust
ipatrust:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
realm: "{{ adserver.domain }}"
state: absent
- name: Clear test idranges
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
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
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
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
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
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
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
when: trust_test_is_supported | default(false)
ansible-freeipa-v1.7.0/tests/trust/test_trust_client_context.yml 0000664 0000000 0000000 00000002332 14232747165 0025336 0 ustar 00root root 0000000 0000000 ---
- name: Test trust
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_trust.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test trust using client context, in server host.
import_playbook: test_trust.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/user/ 0000775 0000000 0000000 00000000000 14232747165 0017066 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/user/certificate/ 0000775 0000000 0000000 00000000000 14232747165 0021350 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/user/certificate/test_user_certificate.yml 0000664 0000000 0000000 00000005367 14232747165 0026465 0 ustar 00root root 0000000 0000000 ---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Generate self-signed certificates.
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.
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
args:
warn: no # suppres warning for not using the `file` module.
ansible-freeipa-v1.7.0/tests/user/certificate/test_users_certificate.yml 0000664 0000000 0000000 00000005775 14232747165 0026653 0 ustar 00root root 0000000 0000000 ---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Generate self-signed certificates.
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.
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
args:
warn: no # suppres warning for not using the `file` module.
ansible-freeipa-v1.7.0/tests/user/certmapdata/ 0000775 0000000 0000000 00000000000 14232747165 0021353 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/user/certmapdata/test_user_certmapdata.yml 0000664 0000000 0000000 00000015541 14232747165 0026466 0 ustar 00root root 0000000 0000000 ---
- name: Test user certmapdata
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Generate self-signed certificates.
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.
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
args:
warn: no # suppres warning for not using the `file` module.
ansible-freeipa-v1.7.0/tests/user/certmapdata/test_user_certmapdata_issuer_subject.yml 0000664 0000000 0000000 00000004354 14232747165 0031577 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-v1.7.0/tests/user/certmapdata/test_users_certmapdata.yml 0000664 0000000 0000000 00000011754 14232747165 0026653 0 ustar 00root root 0000000 0000000 ---
- name: Test user certmapdata
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Generate self-signed certificates.
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.
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
args:
warn: no # suppres warning for not using the `file` module.
ansible-freeipa-v1.7.0/tests/user/create_users_json.yml 0000664 0000000 0000000 00000000422 14232747165 0023324 0 ustar 00root root 0000000 0000000 ---
- name: Create users.json
hosts: localhost
tasks:
- name: Check if users.json exists
stat:
path: users.json
register: register_stat_users
- name: Create users.json
command: /bin/bash users.sh 500
when: not register_stat_users.stat.exists
ansible-freeipa-v1.7.0/tests/user/test_user.yml 0000664 0000000 0000000 00000026072 14232747165 0021635 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
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
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: 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: 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
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: manager1,manager2,manager3,pinky,pinky2
state: absent
ansible-freeipa-v1.7.0/tests/user/test_user_client_context.yml 0000664 0000000 0000000 00000002317 14232747165 0024733 0 ustar 00root root 0000000 0000000 ---
- name: Test user
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
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.
import_playbook: test_user.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test user using client context, in server host.
import_playbook: test_user.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client
ansible-freeipa-v1.7.0/tests/user/test_user_empty_lists.yml 0000664 0000000 0000000 00000005104 14232747165 0024262 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-v1.7.0/tests/user/test_user_empty_string_params.yml 0000664 0000000 0000000 00000010733 14232747165 0026001 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-v1.7.0/tests/user/test_user_random.yml 0000664 0000000 0000000 00000003364 14232747165 0023174 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
debug:
var: ipauser.user.randompassword
- 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
debug:
var: ipauser.user.user1.randompassword
- name: Print generated random password for user2
debug:
var: ipauser.user.user2.randompassword
- name: Users user1 and user2 absent
ipauser:
ipaadmin_password: SomeADMINpassword
name:
- user1
- user2
state: absent
ansible-freeipa-v1.7.0/tests/user/test_users.yml 0000664 0000000 0000000 00000031541 14232747165 0022015 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: 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
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
# 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
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
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-v1.7.0/tests/user/test_users_absent.yml 0000664 0000000 0000000 00000001071 14232747165 0023344 0 ustar 00root root 0000000 0000000 ---
- name: Include create_users_json.yml
import_playbook: create_users_json.yml
- name: Test users absent
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include users.json
include_vars:
file: users.json # noqa 505
- name: Create dict with user names
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-v1.7.0/tests/user/test_users_invalid_cert.yml 0000664 0000000 0000000 00000003406 14232747165 0024537 0 ustar 00root root 0000000 0000000 ---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Generate self-signed certificates.
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.
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
args:
warn: no # suppres warning for not using the `file` module.
ansible-freeipa-v1.7.0/tests/user/test_users_present.yml 0000664 0000000 0000000 00000000610 14232747165 0023546 0 ustar 00root root 0000000 0000000 ---
- name: Include create_users_json.yml
import_playbook: create_users_json.yml
- name: Test users present
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include users.json
include_vars:
file: users.json # noqa 505
- name: Users present len:{{ users | length }}
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ users }}"
ansible-freeipa-v1.7.0/tests/user/test_users_present_slice.yml 0000664 0000000 0000000 00000001057 14232747165 0024733 0 ustar 00root root 0000000 0000000 ---
- name: Include create_users_json.yml
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
include_vars:
file: users.json # noqa 505
- name: Size of users slice.
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-v1.7.0/tests/user/users.sh 0000664 0000000 0000000 00000001161 14232747165 0020562 0 ustar 00root root 0000000 0000000 #!/bin/bash
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-v1.7.0/tests/user/users_absent.sh 0000664 0000000 0000000 00000000562 14232747165 0022122 0 ustar 00root root 0000000 0000000 #!/bin/bash
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-v1.7.0/tests/utils.py 0000664 0000000 0000000 00000020617 14232747165 0017630 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 subprocess
import tempfile
import testinfra
from unittest import TestCase
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
def is_docker_env():
if os.getenv("RUN_TESTS_IN_DOCKER", "0") == "0":
return False
return True
def get_ssh_password():
return os.getenv("IPA_SSH_PASSWORD")
def get_server_host():
return os.getenv("IPA_SERVER_HOST")
def get_inventory_content():
"""Create the content of an inventory file for a test run."""
ipa_server_host = get_server_host()
if is_docker_env():
ipa_server_host += " ansible_connection=docker"
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 = [
"ansible-playbook",
"-i",
inventory_file.name,
playbook,
]
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: {}".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):
if is_docker_env():
protocol = "docker://"
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,
)
def run_playbook(self, playbook, allow_failures=False):
return run_playbook(playbook, allow_failures)
def run_playbook_with_exp_msg(self, playbook, expected_msg):
result = self.run_playbook(playbook, allow_failures=True)
assert (
expected_msg in result.stdout.decode("utf8")
or
expected_msg in result.stderr.decode("utf8")
)
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 output in res.stderr
else:
for output in expected_output:
assert output in res.stdout
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 member not in res.stdout
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-v1.7.0/tests/vault/ 0000775 0000000 0000000 00000000000 14232747165 0017243 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/tests/vault/env_cleanup.yml 0000664 0000000 0000000 00000003157 14232747165 0022273 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.
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.
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-v1.7.0/tests/vault/env_setup.yml 0000664 0000000 0000000 00000002717 14232747165 0022005 0 ustar 00root root 0000000 0000000 ---
# Tasks executed to ensure a sane environment to test IPA Vault module.
- name: Ensure environment is clean.
import_tasks: env_cleanup.yml
- name: Create private/public key pair.
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.
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-v1.7.0/tests/vault/in.txt 0000664 0000000 0000000 00000000016 14232747165 0020407 0 ustar 00root root 0000000 0000000 Another World. ansible-freeipa-v1.7.0/tests/vault/password.txt 0000664 0000000 0000000 00000000022 14232747165 0021640 0 ustar 00root root 0000000 0000000 SomeVAULTpassword
ansible-freeipa-v1.7.0/tests/vault/tasks_vault_members.yml 0000664 0000000 0000000 00000021722 14232747165 0024044 0 ustar 00root root 0000000 0000000 ---
# Tasks to test member management for Vault module.
- name: Setup testing environment.
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.
import_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/vault/test_vault_asymmetric.yml 0000664 0000000 0000000 00000023722 14232747165 0024423 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.
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.
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.
import_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/vault/test_vault_change_type.yml 0000664 0000000 0000000 00000022545 14232747165 0024536 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.
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
- 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.
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
vars:
krb5ccname: verify_change_from_asymmetric
- 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.
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
vars:
krb5ccname: verify_change_from_symmetric
- 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
- 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.
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
vars:
krb5ccname: verify_change_from_symmetric
- 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.
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
vars:
krb5ccname: verify_change_from_asymmetric
- 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'
- 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.
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
vars:
krb5ccname: verify_change_from_asymmetric
- 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'
- 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.
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
vars:
krb5ccname: verify_change_from_symmetric
- 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'
- 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.
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
vars:
krb5ccname: verify_change_from_symmetric
- 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'
- 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.
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
vars:
krb5ccname: verify_change_from_asymmetric
- 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.
import_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/vault/test_vault_client_context.yml 0000664 0000000 0000000 00000001361 14232747165 0025263 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.
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.
import_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/vault/test_vault_members.yml 0000664 0000000 0000000 00000000777 14232747165 0023705 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.
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-v1.7.0/tests/vault/test_vault_standard.yml 0000664 0000000 0000000 00000010264 14232747165 0024043 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.
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.
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.
import_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/tests/vault/test_vault_symmetric.yml 0000664 0000000 0000000 00000026222 14232747165 0024260 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.
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.
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.
import_tasks: env_cleanup.yml
ansible-freeipa-v1.7.0/utils/ 0000775 0000000 0000000 00000000000 14232747165 0016106 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/utils/ansible-doc-test 0000775 0000000 0000000 00000012710 14232747165 0021172 0 ustar 00root root 0000000 0000000 #!/usr/bin/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-v1.7.0/utils/ansible-freeipa.spec.in 0000664 0000000 0000000 00000004471 14232747165 0022423 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}
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: GPLv3+
Source: %{name}-%{version}-@@RELEASE@@.tar.bz2
BuildArch: noarch
%description
ansible-freeipa provides Ansible roles and playbooks to install and uninstall
FreeIPA 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.
%package tests
Summary: ansible-freeipa tests
Requires: %{name}
%description 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
%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
install -m 755 -d %{buildroot}%{_datadir}/ansible/plugins/
cp -rp plugins/* %{buildroot}%{_datadir}/ansible/plugins/
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/plugins/module_utils
%{_datadir}/ansible/plugins/modules
%doc README*.md
%doc playbooks
%files tests
%{_datadir}/ansible-freeipa
%changelog
* @@DATE@@ Thomas Woerner - @@VERSION@@-@@RELEASE@@
- GIT version @@VERSION@@-@@RELEASE@@
ansible-freeipa-v1.7.0/utils/ansible-ipa-client-install 0000775 0000000 0000000 00000043223 14232747165 0023144 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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 sys
import shutil
import tempfile
import argparse
import traceback
import subprocess
def parse_options():
usage = "Usage: ansible-ipa-client-install [options] "
parser = argparse.ArgumentParser(usage=usage)
parser.add_argument("--version", dest="version",
action="store_true",
help="show program's version number and exit")
parser.add_argument("-U", "--unattended", dest="unattended",
action="store_true",
help="unattended (un)installation never prompts the "
"user")
parser.add_argument("--uninstall", dest="uninstall",
action="store_true",
help="uninstall an existing installation. The "
"uninstall can be run with --unattended option")
# basic
parser.add_argument("-p", "--principal", dest="principal",
default=None,
help="principal to use to join the IPA realm")
parser.add_argument("--ca-cert-file", dest="ca_cert_file",
default=None,
help="load the CA certificate from this file")
parser.add_argument("--ip-address", dest="ip_addresses",
metavar="IP_ADDRESS",
action='append', default=None,
help="Specify IP address that should be added to DNS. "
"This option can be used multiple times")
parser.add_argument("--all-ip-addresses", dest="all_ip_addresses",
action='store_true',
help="All routable IP addresses configured on any "
"interface will be added to DNS")
parser.add_argument("--domain", dest="domain",
default=None,
help="primary DNS domain of the IPA deployment (not "
"necessarily related to the current hostname)")
parser.add_argument("--server", dest="servers",
metavar="SERVER",
action='append', default=None,
help="FQDN of IPA server")
parser.add_argument("--realm", dest="realm",
default=None,
help="Kerberos realm name of the IPA deployment "
"(typically an upper-cased name of the primary DNS "
"domain)")
parser.add_argument("--hostname", dest="hostname",
default=None,
help="The hostname of this machine (FQDN). If "
"specified, the hostname will be set and the system "
"configuration will be updated to persist over "
"reboot. By default the result of getfqdn() call "
"from Python's socket module is used.")
# client
parser.add_argument("-w", "--password", dest="password",
default=None,
help="password to join the IPA realm (assumes bulk "
"password unless principal is also set)")
parser.add_argument("-W", dest="password_prompt",
action="store_true",
help="Prompt for a password to join the IPA realm")
parser.add_argument("-f", "--force", dest="force",
action="store_true",
help="force setting of LDAP/Kerberos conf")
parser.add_argument("--configure-firefox", dest="configure_firefox",
action="store_true",
help="configure Firefox to use IPA domain credentials")
parser.add_argument("--firefox-dir", dest="firefox_dir",
default=None,
help="specify directory where Firefox is installed "
"(for example: '/usr/lib/firefox')")
parser.add_argument("-k", "--keytab", dest="keytab",
default=None,
help="path to backed up keytab from previous "
"enrollment")
parser.add_argument("--mkhomedir", dest="mkhomedir",
action="store_true",
help="create home directories for users on their "
"first login")
parser.add_argument("--force-join", dest="force_join",
action="store_true",
help="Force client enrollment even if already "
"enrolled")
parser.add_argument("--ntp-server", dest="ntp_servers",
metavar="NTP_SERVER",
action='append', default=None,
help="ntp server to use. This option can be used "
"multiple times")
parser.add_argument("--ntp-pool", dest="ntp_pool",
default=None,
help="ntp server pool to use")
parser.add_argument("-N", "--no-ntp", dest="no_ntp",
action="store_true",
help="do not configure ntp")
parser.add_argument("--nisdomain", dest="nisdomain",
default=None,
help="NIS domain name")
parser.add_argument("--no-nisdomain", dest="no_nisdomain",
action="store_true",
help="do not configure NIS domain name")
parser.add_argument("--ssh-trust-dns", dest="ssh_trust_dns",
action="store_true",
help="configure OpenSSH client to trust DNS SSHFP "
"records")
parser.add_argument("--no-ssh", dest="no_ssh",
action="store_true",
help="do not configure OpenSSH client")
parser.add_argument("--no-sshd", dest="no_sshd",
action="store_true",
help="do not configure OpenSSH server")
parser.add_argument("--no-sudo", dest="no_sudo",
action="store_true",
help="do not configure SSSD as data source for sudo")
parser.add_argument("--no-dns-sshfp", dest="no_dns_sshfp",
action="store_true",
help="do not automatically create DNS SSHFP records")
parser.add_argument("--kinit-attempts", dest="kinit_attempts",
type=int, default=None,
help="number of attempts to obtain host TGT (defaults "
"to 5)")
# sssd
parser.add_argument("--fixed-primary", dest="fixed_primary",
action="store_true",
help="Configure sssd to use fixed server as primary "
"IPA server")
parser.add_argument("--permit", dest="permit",
action="store_true",
help="disable access rules by default, permit all "
"access")
parser.add_argument("--enable-dns-updates", dest="enable_dns_updates",
action="store_true",
help="Configures the machine to attempt dns updates "
"when the ip address changes")
parser.add_argument("--no-krb5-offline-passwords",
dest="no_krb5_offline_passwords",
action="store_true",
help="Configure SSSD not to store user password when "
"the server is offline")
parser.add_argument("--preserve-sssd", dest="preserve_sssd",
action="store_true",
help="Preserve old SSSD configuration if possible")
# automount
parser.add_argument("--automount-location", dest="automount_location",
default=None,
help="Automount location")
# logging and output
parser.add_argument("-v", "--verbose", dest="verbose",
action="store_true",
help="print debugging information")
parser.add_argument("-d", "--debug", dest="verbose",
action="store_true",
help="alias for --verbose (deprecated)")
parser.add_argument("-q", "--quiet", dest="quiet",
action="store_true",
help="output only errors")
parser.add_argument("--log-file", dest="log_file",
help="log to the given file")
# ansible
parser.add_argument("--ipaclient-use-otp", dest="ipaclient_use_otp",
choices=("yes", "no"), default=None,
help="The bool value defines if a one-time password "
"will be generated to join a new or existing host. "
"Default: no")
parser.add_argument("--ipaclient-allow-repair",
dest="ipaclient_allow_repair",
choices=("yes", "no"), default=None,
help="The bool value defines if an already joined or "
"partly set-up client can be repaired. Default: no")
parser.add_argument("--ipaclient-install-packages",
dest="ipaclient_install_packages",
choices=("yes", "no"), default=None,
help="The bool value defines if the needed packages "
"are installed on the node. Default: yes")
# playbook
parser.add_argument("--playbook-dir",
dest="playbook_dir",
default=None,
help="If defined will be used as to create inventory "
"file and playbook in. The files will not be removed "
"after the playbook processing ended.")
parser.add_argument("--become-method",
dest="become_method",
default="sudo",
help="privilege escalation method to use "
"(default=sudo), use `ansible-doc -t become -l` to "
"list valid choices.")
parser.add_argument("--ansible-verbose",
dest="ansible_verbose",
type=int, default=None,
help="privilege escalation method to use "
"(default=sudo), use `ansible-doc -t become -l` to "
"list valid choices.")
options, args = parser.parse_known_args()
if options.playbook_dir and not os.path.isdir(options.playbook_dir):
parser.error("playbook dir does not exist")
if options.password_prompt:
parser.error("password prompt is not possible with ansible")
if options.log_file:
parser.error("log_file is not supported")
if len(args) < 1:
parser.error("ansible host not set")
elif len(args) > 1:
parser.error("too many arguments: %s" % ",".join(args))
return options, args
def run_cmd(args):
"""
Execute an external command.
"""
p_out = subprocess.PIPE
p_err = subprocess.STDOUT
try:
p = subprocess.Popen(args, stdout=p_out, stderr=p_err,
close_fds=True, bufsize=1,
universal_newlines=True)
while True:
line = p.stdout.readline()
if p.poll() is not None and line == "":
break
sys.stdout.write(line)
except KeyboardInterrupt:
p.wait()
raise
else:
p.wait()
return p.returncode
def main(options, args):
if options.playbook_dir:
playbook_dir = options.playbook_dir
else:
temp_dir = tempfile.mkdtemp(prefix='ansible-ipa-client')
playbook_dir = temp_dir
inventory = os.path.join(playbook_dir, "ipaclient-inventory")
playbook = os.path.join(playbook_dir, "ipaclient-playbook.yml")
with open(inventory, 'w') as f:
if options.servers:
f.write("[ipaservers]\n")
for server in options.servers:
f.write("%s\n" % server)
f.write("\n")
f.write("[ipaclients]\n")
f.write("%s\n" % args[0])
f.write("\n")
f.write("[ipaclients:vars]\n")
# basic
if options.principal:
f.write("ipaadmin_principal=%s\n" % options.principal)
if options.ca_cert_file:
f.write("ipaclient_ca_cert_file=%s\n" % options.ca_cert_file)
if options.ip_addresses:
f.write("ipaclient_ip_addresses=%s\n" %
",".join(options.ip_addresses))
if options.all_ip_addresses:
f.write("ipaclient_all_ip_addresses=yes\n")
if options.domain:
f.write("ipaclient_domain=%s\n" % options.domain)
# --servers are handled above
if options.realm:
f.write("ipaclient_realm=%s\n" % options.realm)
if options.hostname:
f.write("ipaclient_hostname=%s\n" % options.hostname)
# client
if options.password:
f.write("ipaadmin_password=%s\n" % options.password)
if options.force:
f.write("ipaclient_force=yes\n")
if options.configure_firefox:
f.write("ipaclient_configure_firefox=yes\n")
if options.firefox_dir:
f.write("ipaclient_firefox_dir=%s\n" % options.firefox_dir)
if options.keytab:
f.write("ipaclient_keytab=%s\n" % options.keytab)
if options.mkhomedir:
f.write("ipaclient_mkhomedir=yes\n")
if options.force_join:
f.write("ipaclient_force_join=%s\n" % options.force_join)
if options.ntp_servers:
f.write("ipaclient_ntp_servers=%s\n" %
",".join(options.ntp_servers))
if options.ntp_pool:
f.write("ipaclient_ntp_pool=%s\n" % options.ntp_pool)
if options.no_ntp:
f.write("ipaclient_no_ntp=yes\n")
if options.nisdomain:
f.write("ipaclient_nisdomain=%s\n" % options.nisdomain)
if options.no_nisdomain:
f.write("ipaclient_no_nisdomain=yes\n")
if options.ssh_trust_dns:
f.write("ipaclient_ssh_trust_dns=yes\n")
if options.no_ssh:
f.write("ipaclient_no_ssh=yes\n")
if options.no_sshd:
f.write("ipaclient_no_sshd=yes\n")
if options.no_sudo:
f.write("ipaclient_no_sudo=yes\n")
if options.no_dns_sshfp:
f.write("ipaclient_no_dns_sshfp=yes\n")
if options.kinit_attempts:
f.write("ipaclient_kinit_attempts=%d\n" % options.kinit_attempts)
# sssd
if options.fixed_primary:
f.write("ipasssd_fixed_primary=yes\n")
if options.permit:
f.write("ipasssd_permit=yes\n")
if options.enable_dns_updates:
f.write("ipasssd_enable_dns_updates=yes\n")
if options.no_krb5_offline_passwords:
f.write("ipasssd_no_krb5_offline_passwords=yes\n")
if options.preserve_sssd:
f.write("ipasssd_preserve_sssd=yes\n")
# automount
if options.automount_location:
f.write("ipaclient_automount_location=%s\n" %
options.automount_location)
# ansible
if options.ipaclient_use_otp:
f.write("ipaclient_use_otp=%s\n" % options.ipaclient_use_otp)
if options.ipaclient_allow_repair:
f.write("ipaclient_allow_repair=%s\n" %
options.ipaclient_allow_repair)
if options.ipaclient_install_packages:
f.write("ipaclient_install_packages=%s\n" %
options.ipaclient_install_packages)
if options.uninstall:
state = "absent"
else:
state = "present"
with open(playbook, 'w') as f:
f.write("---\n")
f.write("- name: Playbook to configure IPA clients\n")
f.write(" hosts: ipaclients\n")
f.write(" become: true\n")
if options.become_method:
f.write(" become_method: %s\n" % options.become_method)
f.write("\n")
f.write(" roles:\n")
f.write(" - role: ipaclient\n")
f.write(" state: %s\n" % state)
cmd = [ 'ansible-playbook' ]
if options.ansible_verbose:
cmd.append("-"+"v"*options.ansible_verbose)
cmd.extend(['-i', inventory, playbook])
try:
returncode = run_cmd(cmd)
if returncode != 0:
raise RuntimeError()
finally:
if not options.playbook_dir:
shutil.rmtree(temp_dir, ignore_errors=True)
options, args = parse_options()
try:
main(options, args)
except KeyboardInterrupt:
sys.exit(1)
except SystemExit as e:
sys.exit(e)
except RuntimeError as e:
sys.exit(e)
except Exception as e:
if options.verbose:
traceback.print_exc(file=sys.stdout)
else:
print("Re-run %s with --verbose option to get more information" %
sys.argv[0])
print("Unexpected error: %s" % str(e))
sys.exit(1)
ansible-freeipa-v1.7.0/utils/ansible-ipa-replica-install 0000775 0000000 0000000 00000057526 14232747165 0023320 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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 sys
import shutil
import tempfile
import argparse
import traceback
import subprocess
def parse_options():
usage = "Usage: anisble-ipa-replica-install [options] "
parser = argparse.ArgumentParser(usage=usage)
parser.add_argument("--version", dest="version",
action="store_true",
help="show program's version number and exit")
parser.add_argument("-U", "--unattended", dest="unattended",
action="store_true",
help="unattended (un)installation never prompts the "
"user")
# basic
parser.add_argument("-w", "--admin-password", dest="admin_password",
default=None,
help="Kerberos password for the specified admin "
"principal")
parser.add_argument("--ip-address", dest="ip_addresses",
metavar="IP_ADDRESS",
action='append', default=None,
help="Replica server IP Address. This option can be "
"used multiple times")
parser.add_argument("-n", "--domain", dest="domain",
metavar="DOMAIN_NAME", default=None,
help="primary DNS domain of the IPA deployment (not "
"necessarily related to the current hostname)")
parser.add_argument("--server", dest="servers",
metavar="SERVER",
action='append', default=None,
help="fully qualified name of IPA server to enroll to")
parser.add_argument("-r", "--realm", dest="realm",
metavar="REALM_NAME", default=None,
help="Kerberos realm name of the IPA deployment "
"(typically un upper-cased name of the primary DNS "
"domain)")
parser.add_argument("--hostname", dest="hostname",
metavar="HOST_NAME", default=None,
help="fully qualified name of this host")
parser.add_argument("-P", "--principal", dest="principal",
default=None,
help="User Principal allowed to promote replicas and "
"join IPA realm")
parser.add_argument("--pki-config-override", dest="pki_config_override",
default=None,
help="Path to ini file with config overrides.")
parser.add_argument("--no-host-dns", dest="no_host_dns",
action="store_true",
help="Do not use DNS for hostname lookup during "
"installation")
parser.add_argument("--skip-conncheck", dest="skip_conncheck",
action="store_true",
help="skip connection check to remote master")
# server
parser.add_argument("-p", "--password", dest="dm_password",
default=None,
help="Password to join the IPA realm. Assumes bulk "
"password unless principal is also set. (domain "
"level 1+) Directory Manager (existing master) "
"password. (domain level 0)")
parser.add_argument("--hidden-replica", dest="hidden_replica",
action="store_true",
help="Install a hidden replica")
parser.add_argument("--setup-adtrust", dest="setup_adtrust",
action="store_true",
help="configure AD trust capability")
parser.add_argument("--setup-ca", dest="setup_ca",
action="store_true",
help="configure a dogtag CA")
parser.add_argument("--setup-kra", dest="setup_kra",
action="store_true",
help="configure a dogtag KRA")
parser.add_argument("--setup-dns", dest="setup_dns",
action="store_true",
help="configure bind with our zone")
parser.add_argument("--no-pkinit", dest="no_pkinit",
action="store_true",
help="disables pkinit setup steps")
parser.add_argument("--no-ui-redirect", dest="no_ui_redirect",
action="store_true",
help="Do not automatically redirect to the Web UI")
parser.add_argument("--dirsrv-config-file", dest="dirsrv_config_file",
metavar="FILE", default=None,
help="The path to LDIF file that will be used to "
"modify configuration of dse.ldif during "
"installation of the directory server instance")
# ssl certificate
parser.add_argument("--dirsrv-cert-file", dest="dirsrv_cert_files",
metavar="FILE", default=None, action="append",
help="File containing the Directory Server SSL "
"certificate and private key")
parser.add_argument("--http-cert-file", dest="http_cert_files",
metavar="FILE", default=None, action="append",
help="File containing the Apache Server SSL "
"certificate and private key")
parser.add_argument("--pkinit-cert-file", dest="pkinit_cert_files",
metavar="FILE", default=None, action="append",
help="File containing the Kerberos KDC SSL "
"certificate and Private key")
parser.add_argument("--dirsrv-pin", dest="dirsrv_pin",
metavar="PIN", default=None,
help="The password to unlock the Directory Server "
"private key")
parser.add_argument("--http-pin", dest="http_pin",
metavar="PIN", default=None,
help="The password to unlock the Apache Server "
"private key")
parser.add_argument("--pkinit-pin", dest="pkinit_pin",
metavar="PIN", default=None,
help="The password to unlock the Kerberos KDC "
"private key")
parser.add_argument("--dirsrv-cert-name", dest="dirsrv_cert_name",
metavar="NAME", default=None,
help="Name of the Directory Server SSL certificate "
"to install")
parser.add_argument("--http-cert-name", dest="http_cert_name",
metavar="NAME", default=None,
help="Name of the Apache Server SSL certificate to "
"install")
parser.add_argument("--pkinit-cert-name", dest="pkinit_cert_name",
metavar="NAME", default=None,
help="Name of the Kerberos KDC SSL certificate to "
"install")
# client
parser.add_argument("-k", "--keytab", dest="keytab",
default=None,
help="path to backed up keytab from previous "
"enrollment")
parser.add_argument("--mkhomedir", dest="mkhomedir",
action="store_true",
help="create home directories for users on their "
"first login")
parser.add_argument("--force-join", dest="force_join",
action="store_true",
help="Force client enrollment even if already "
"enrolled")
parser.add_argument("--ntp-server", dest="ntp_servers",
metavar="NTP_SERVER",
action='append', default=None,
help="ntp server to use. This option can be used "
"multiple times")
parser.add_argument("--ntp-pool", dest="ntp_pool",
default=None,
help="ntp server pool to use")
parser.add_argument("-N", "--no-ntp", dest="no_ntp",
action="store_true",
help="do not configure ntp")
parser.add_argument("--ssh-trust-dns", dest="ssh_trust_dns",
action="store_true",
help="configure OpenSSH client to trust DNS SSHFP "
"records")
parser.add_argument("--no-ssh", dest="no_ssh",
action="store_true",
help="do not configure OpenSSH client")
parser.add_argument("--no-sshd", dest="no_sshd",
action="store_true",
help="do not configure OpenSSH server")
parser.add_argument("--no-dns-sshfp", dest="no_dns_sshfp",
action="store_true",
help="do not automatically create DNS SSHFP records")
# certificate system
parser.add_argument("--skip-schema-check", dest="skip_schema_check",
action="store_true",
help="skip check for updated CA DS schema on the "
"remote master")
# dns
parser.add_argument("--allow-zone-overlap", dest="allow_zone_overlap",
action="store_true",
help="Create DNS zone even if it already exists")
parser.add_argument("--reverse-zone", dest="reverse_zones",
metavar="REVERSE_ZONE", action="append", default=None,
help="The reverse DNS zone to use. This option can "
"be used multiple times")
parser.add_argument("--no-reverse", dest="no_reverse",
action="store_true",
help="Do not create new reverse DNS zone")
parser.add_argument("--auto-reverse", dest="auto_reverse",
action="store_true",
help="Create necessary reverse zones")
parser.add_argument("--forwarder", dest="forwarders",
action="append", default=None,
help="Add a DNS forwarder. This option can be used "
"multiple times")
parser.add_argument("--no-forwarders", dest="no_forwarders",
action="store_true",
help="Do not add any DNS forwarders, use root "
"servers instead")
parser.add_argument("--auto-forwarders", dest="auto_forwarders",
action="store_true",
help="Use DNS forwarders configured in "
"/etc/resolv.conf")
parser.add_argument("-forward-policy-", dest="forward_policy",
choices=("only", "first"), default=None,
help="DNS forwarding policy for global forwarders")
parser.add_argument("--no-dnssec-validation", dest="no_dnssec_validation",
action="store_true",
help="Disable DNSSEC validation")
# ad trust
parser.add_argument("--add-sids", dest="add_sids",
action="store_true",
help="Add SIDs for existing users and groups as the "
"final step")
parser.add_argument("--add-agents", dest="add_agents",
action="store_true",
help="Add IPA masters to a list of hosts allowed to "
"serve information about users from trusted forests")
parser.add_argument("--enable-compat", dest="enable_compat",
action="store_true",
help="Enable support for trusted domains for old "
"clients")
parser.add_argument("--netbios-name", dest="netbios_name",
default=None,
help="NetBIOS name of the IPA domain")
parser.add_argument("--rid-base", dest="rid_base",
default=None, type=int,
help="Start value for mapping UIDs and GIDs to RIDs")
parser.add_argument("--secondary-rid-base", dest="secondary_rid_base",
default=None, type=int,
help="Start value of the secondary range for mapping "
"UIDs and GIDs to RIDs")
# logging and output
parser.add_argument("-v", "--verbose", dest="verbose",
action="store_true",
help="print debugging information")
parser.add_argument("-d", "--debug", dest="verbose",
action="store_true",
help="alias for --verbose (deprecated)")
parser.add_argument("-q", "--quiet", dest="quiet",
action="store_true",
help="output only errors")
parser.add_argument("--log-file", dest="log_file",
help="log to the given file")
# ansible
parser.add_argument("--ipareplica-install-packages",
dest="ipareplica_install_packages",
choices=("yes", "no"), default=None,
help="The bool value defines if the needed packages "
"are installed on the node. Default: yes")
parser.add_argument("--ipareplica-setup-firewalld",
dest="ipareplica_setup_firewalld",
choices=("yes", "no"), default=None,
help="The value defines if the needed services will "
"automatically be openen in the firewall managed by "
"firewalld. Default: yes")
# playbook
parser.add_argument("--playbook-dir",
dest="playbook_dir",
default=None,
help="If defined will be used as to create inventory "
"file and playbook in. The files will not be removed "
"after the playbook processing ended.")
parser.add_argument("--become-method",
dest="become_method",
default="sudo",
help="privilege escalation method to use "
"(default=sudo), use `ansible-doc -t become -l` to "
"list valid choices.")
parser.add_argument("--ansible-verbose",
dest="ansible_verbose",
type=int, default=None,
help="privilege escalation method to use "
"(default=sudo), use `ansible-doc -t become -l` to "
"list valid choices.")
options, args = parser.parse_known_args()
if options.playbook_dir and not os.path.isdir(options.playbook_dir):
parser.error("playbook dir does not exist")
if options.log_file:
parser.error("log_file is not supported")
if len(args) < 1:
parser.error("ansible host not set")
elif len(args) > 1:
parser.error("too many arguments: %s" % ",".join(args))
return options, args
def run_cmd(args):
"""
Execute an external command.
"""
p_out = subprocess.PIPE
p_err = subprocess.STDOUT
try:
p = subprocess.Popen(args, stdout=p_out, stderr=p_err,
close_fds=True, bufsize=1,
universal_newlines=True)
while True:
line = p.stdout.readline()
if p.poll() is not None and line == "":
break
sys.stdout.write(line)
except KeyboardInterrupt:
p.wait()
raise
else:
p.wait()
return p.returncode
def main(options, args):
if options.playbook_dir:
playbook_dir = options.playbook_dir
else:
temp_dir = tempfile.mkdtemp(prefix='ansible-ipa-replica')
playbook_dir = temp_dir
inventory = os.path.join(playbook_dir, "ipareplica-inventory")
playbook = os.path.join(playbook_dir, "ipareplica-playbook.yml")
with open(inventory, 'w') as f:
if options.servers:
f.write("[ipaservers]\n")
for server in options.servers:
f.write("%s\n" % server)
f.write("\n")
f.write("[ipareplicas]\n")
f.write("%s\n" % args[0])
f.write("\n")
f.write("[ipareplicas:vars]\n")
# basic
if options.admin_password:
f.write("ipaadmin_password=%s\n" % options.admin_password)
if options.ip_addresses:
f.write("ipareplica_ip_addresses=%s\n" %
",".join(options.ip_addresses))
if options.domain:
f.write("ipareplica_domain=%s\n" % options.domain)
# --servers are handled above
if options.realm:
f.write("ipareplica_realm=%s\n" % options.realm)
if options.hostname:
f.write("ipareplica_hostname=%s\n" % options.hostname)
if options.principal:
f.write("ipaadmin_principal=%s\n" % options.principal)
if options.pki_config_override:
f.write("ipareplica_pki_config_override=yes\n")
if options.no_host_dns:
f.write("ipareplica_no_host_dns=yes\n")
if options.skip_conncheck:
f.write("ipareplica_skip_conncheck=yes\n")
# server
if options.dm_password:
f.write("ipadm_password=%s\n" % options.dm_password)
if options.hidden_replica:
f.write("ipareplica_hidden_replica=yes\n")
if options.setup_adtrust:
f.write("ipareplica_setup_adtrust=yes\n")
if options.setup_ca:
f.write("ipareplica_setup_ca=yes\n")
if options.setup_kra:
f.write("ipareplica_setup_kra=yes\n")
if options.setup_dns:
f.write("ipareplica_setup_dns=yes\n")
if options.no_pkinit:
f.write("ipareplica_no_pkinit=yes\n")
if options.no_ui_redirect:
f.write("ipareplica_no_ui_redirect=yes\n")
# ssl certificate
if options.dirsrv_cert_files:
f.write("ipareplica_dirsrv_cert_files=%s\n" %
",".join(options.dirsrv_cert_files))
if options.http_cert_files:
f.write("ipareplica_http_cert_files=%s\n" %
",".join(options.http_cert_files))
if options.pkinit_cert_files:
f.write("ipareplica_pkinit_cert_files=%s\n" %
",".join(options.pkinit_cert_files))
if options.dirsrv_pin:
f.write("ipareplica_dirsrv_pin=%s\n" % options.dirsrv_pin)
if options.http_pin:
f.write("ipareplica_http_pin=%s\n" % options.http_pin)
if options.pkinit_pin:
f.write("ipareplica_pkinit_pin=%s\n" % options.pkinit_pin)
if options.dirsrv_cert_name:
f.write("ipareplica_dirsrv_cert_name=%s\n" %
options.dirsrv_cert_name)
if options.http_cert_name:
f.write("ipareplica_http_cert_name=%s\n" % options.http_cert_name)
if options.pkinit_cert_name:
f.write("ipareplica_pkinit_cert_name=%s\n" %
options.pkinit_cert_name)
# client
if options.keytab:
f.write("ipaclient_keytab=%s\n" % options.keytab)
if options.mkhomedir:
f.write("ipaclient_mkhomedir=yes\n")
if options.force_join:
f.write("ipaclient_force_join=yes\n")
if options.ntp_servers:
f.write("ipaclient_ntp_server=%s\n" %
",".join(options.ntp_replicas))
if options.ntp_pool:
f.write("ipaclient_ntp_pool=%s\n" % options.ntp_pool)
if options.no_ntp:
f.write("ipaclient_no_ntp=yes\n")
if options.ssh_trust_dns:
f.write("ipaclient_ssh_trust_dns=yes\n")
if options.no_ssh:
f.write("ipaclient_no_ssh=yes\n")
if options.no_sshd:
f.write("ipaclient_no_sshd=yes\n")
if options.no_dns_sshfp:
f.write("ipaclient_no_dns_sshfp=yes\n")
# certificate system
if options.skip_schema_check:
f.write("ipareplica_skip_schema_check=yes\n")
# dns
if options.allow_zone_overlap:
f.write("ipareplica_allow_zone_overlap=yes\n")
if options.reverse_zones:
f.write("ipareplica_reverse_zones=%s\n" %
",".join(options.reverse_zones))
if options.no_reverse:
f.write("ipareplica_no_reverse=yes\n")
if options.auto_reverse:
f.write("ipareplica_auto_reverse=yes\n")
if options.forwarders:
f.write("ipareplica_forwarders=%s\n" %
",".join(options.forwarders))
if options.no_forwarders:
f.write("ipareplica_no_forwarders=yes\n")
if options.auto_forwarders:
f.write("ipareplica_auto_forwarders=yes\n")
if options.forward_policy:
f.write("ipareplica_forward_policy=%s\n" % options.forward_policy)
if options.no_dnssec_validation:
f.write("ipareplica_no_dnssec_validation=yes\n")
# ad trust
if options.add_sids:
f.write("ipareplica_add_sids=yes\n")
if options.add_agents:
f.write("ipareplica_add_agents=yes\n")
if options.enable_compat:
f.write("ipareplica_enable_compat=yes\n")
if options.netbios_name:
f.write("ipareplica_netbios_name=%s\n" % options.netbios_name)
if options.rid_base:
f.write("ipareplica_rid_base=%s\n" % options.rid_base)
if options.secondary_rid_base:
f.write("ipareplica_secondary_rid_base=%s\n" %
options.secondary_rid_base)
# ansible
if options.ipareplica_install_packages:
f.write("ipareplica_install_packages=%s\n" %
options.ipareplica_install_packages)
if options.ipareplica_setup_firewalld:
f.write("ipareplica_setup_firewalld=%s\n" %
options.ipareplica_setup_firewalld)
# uninstall done with ipaserver role
state = "present"
with open(playbook, 'w') as f:
f.write("---\n")
f.write("- name: Playbook to configure IPA replicas\n")
f.write(" hosts: ipareplicas\n")
f.write(" become: true\n")
if options.become_method:
f.write(" become_method: %s\n" % options.become_method)
f.write("\n")
f.write(" roles:\n")
f.write(" - role: ipareplica\n")
f.write(" state: %s\n" % state)
cmd = [ 'ansible-playbook' ]
if options.ansible_verbose:
cmd.append("-"+"v"*options.ansible_verbose)
cmd.extend(['-i', inventory, playbook])
try:
returncode = run_cmd(cmd)
if returncode != 0:
raise RuntimeError()
finally:
if not options.playbook_dir:
shutil.rmtree(temp_dir, ignore_errors=True)
options, args = parse_options()
try:
main(options, args)
except KeyboardInterrupt:
sys.exit(1)
except SystemExit as e:
sys.exit(e)
except RuntimeError as e:
sys.exit(e)
except Exception as e:
if options.verbose:
traceback.print_exc(file=sys.stdout)
else:
print("Re-run %s with --verbose option to get more information" %
sys.argv[0])
print("Unexpected error: %s" % str(e))
sys.exit(1)
ansible-freeipa-v1.7.0/utils/ansible-ipa-server-install 0000775 0000000 0000000 00000066430 14232747165 0023201 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019 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 sys
import shutil
import tempfile
import argparse
import traceback
import subprocess
def parse_options():
usage = "Usage: anisble-ipa-server-install [options] "
parser = argparse.ArgumentParser(usage=usage)
parser.add_argument("--version", dest="version",
action="store_true",
help="show program's version number and exit")
parser.add_argument("-U", "--unattended", dest="unattended",
action="store_true",
help="unattended (un)installation never prompts the "
"user")
parser.add_argument("--uninstall", dest="uninstall",
action="store_true",
help="uninstall an existing installation. The "
"uninstall can be run with --unattended option")
# basic
parser.add_argument("-p", "--ds-password", dest="dm_password",
default=None,
help="Directory Manager password")
parser.add_argument("-a", "--admin-password", dest="admin_password",
default=None,
help="admin user kerberos password")
parser.add_argument("--ip-address", dest="ip_addresses",
metavar="IP_ADDRESS",
action='append', default=None,
help="Master Server IP Address. This option can be "
"used multiple times")
parser.add_argument("-n", "--domain", dest="domain",
metavar="DOMAIN_NAME", default=None,
help="primary DNS domain of the IPA deployment (not "
"necessarily related to the current hostname)")
parser.add_argument("-r", "--realm", dest="realm",
metavar="REALM_NAME", default=None,
help="Kerberos realm name of the IPA deployment "
"(typically un upper-cased name of the primary DNS "
"domain)")
parser.add_argument("--hostname", dest="hostname",
metavar="HOST_NAME", default=None,
help="fully qualified name of this host")
parser.add_argument("--ca-cert-file", dest="ca_cert_file",
metavar="FILE", default=None,
help="File containing CA certificates for the "
"service certificate files")
parser.add_argument("--pki-config-override", dest="pki_config_override",
default=None,
help="Path to ini file with config overrides.")
parser.add_argument("--no-host-dns", dest="no_host_dns",
action="store_true",
help="Do not use DNS for hostname lookup during "
"installation")
# server
parser.add_argument("--setup-adtrust", dest="setup_adtrust",
action="store_true",
help="configure AD trust capability")
parser.add_argument("--setup-kra", dest="setup_kra",
action="store_true",
help="configure a dogtag KRA")
parser.add_argument("--setup-dns", dest="setup_dns",
action="store_true",
help="configure bind with our zone")
parser.add_argument("--idstart", dest="idstart",
type=int, default=None,
help="The starting value for the IDs range (default "
"random)")
parser.add_argument("--idmax", dest="idmax",
default=None, type=int,
help="The max value for the IDs range (default: "
"idstart+199999)")
parser.add_argument("--no-hbac-allow", dest="no_hbac_allow",
action="store_true",
help="Don't install allow_all HBAC rule")
parser.add_argument("--no-pkinit", dest="no_pkinit",
action="store_true",
help="disables pkinit setup steps")
parser.add_argument("--no-ui-redirect", dest="no_ui_redirect",
action="store_true",
help="Do not automatically redirect to the Web UI")
parser.add_argument("--dirsrv-config-file", dest="dirsrv_config_file",
metavar="FILE", default=None,
help="The path to LDIF file that will be used to "
"modify configuration of dse.ldif during "
"installation of the directory server instance")
# ssl certificate
parser.add_argument("--dirsrv-cert-file", dest="dirsrv_cert_files",
metavar="FILE", default=None, action="append",
help="File containing the Directory Server SSL "
"certificate and private key")
parser.add_argument("--http-cert-file", dest="http_cert_files",
metavar="FILE", default=None, action="append",
help="File containing the Apache Server SSL "
"certificate and private key")
parser.add_argument("--pkinit-cert-file", dest="pkinit_cert_files",
metavar="FILE", default=None, action="append",
help="File containing the Kerberos KDC SSL "
"certificate and Private key")
parser.add_argument("--dirsrv-pin", dest="dirsrv_pin",
metavar="PIN", default=None,
help="The password to unlock the Directory Server "
"private key")
parser.add_argument("--http-pin", dest="http_pin",
metavar="PIN", default=None,
help="The password to unlock the Apache Server "
"private key")
parser.add_argument("--pkinit-pin", dest="pkinit_pin",
metavar="PIN", default=None,
help="The password to unlock the Kerberos KDC "
"private key")
parser.add_argument("--dirsrv-cert-name", dest="dirsrv_cert_name",
metavar="NAME", default=None,
help="Name of the Directory Server SSL certificate "
"to install")
parser.add_argument("--http-cert-name", dest="http_cert_name",
metavar="NAME", default=None,
help="Name of the Apache Server SSL certificate to "
"install")
parser.add_argument("--pkinit-cert-name", dest="pkinit_cert_name",
metavar="NAME", default=None,
help="Name of the Kerberos KDC SSL certificate to "
"install")
# client
parser.add_argument("--mkhomedir", dest="mkhomedir",
action="store_true",
help="create home directories for users on their "
"first login")
parser.add_argument("--ntp-server", dest="ntp_servers",
metavar="NTP_SERVER",
action='append', default=None,
help="ntp server to use. This option can be used "
"multiple times")
parser.add_argument("--ntp-pool", dest="ntp_pool",
default=None,
help="ntp server pool to use")
parser.add_argument("-N", "--no-ntp", dest="no_ntp",
action="store_true",
help="do not configure ntp")
parser.add_argument("--ssh-trust-dns", dest="ssh_trust_dns",
action="store_true",
help="configure OpenSSH client to trust DNS SSHFP "
"records")
parser.add_argument("--no-ssh", dest="no_ssh",
action="store_true",
help="do not configure OpenSSH client")
parser.add_argument("--no-sshd", dest="no_sshd",
action="store_true",
help="do not configure OpenSSH server")
parser.add_argument("--no-dns-sshfp", dest="no_dns_sshfp",
action="store_true",
help="do not automatically create DNS SSHFP records")
# certificate system
parser.add_argument("--external-ca", dest="external_ca",
action="store_true",
help="Generate a CSR for the IPA CA certificate to "
"be signed by an external CA")
parser.add_argument("--external-ca-type", dest="external_ca_type",
choices=("generic", "ms-cs"), default=None,
help="Type of the external CA")
parser.add_argument("--external-ca-profile", dest="external_ca_profile",
default=None,
help="Specify the certificate profile/template to "
"use at the external CA")
parser.add_argument("--external-cert-file", dest="external_cert_files",
metavar="FILE", default=None, action="append",
help="File containing the IPA CA certificate and the "
"external CA certificate chain")
parser.add_argument("--subject-base", dest="subject_base",
default=None,
help="The certificate subject base (default "
"O=). RDNs are in LDAP order (most "
"specific RDN first).")
parser.add_argument("--ca-subject", dest="ca_subject",
default=None,
help="The CA certificate subject DN (default "
"CN=Certificate Authority,O=). RDNs are "
"in LDAP order (most specific RDN first).")
parser.add_argument("--ca-signing-algorithm", dest="ca_signing_algorithm",
choices=("SHA1withRSA", "SHA256withRSA",
"SHA512withRSA"),
default=None,
help="Signing algorithm of the IPA CA certificate")
# dns
parser.add_argument("--allow-zone-overlap", dest="allow_zone_overlap",
action="store_true",
help="Create DNS zone even if it already exists")
parser.add_argument("--reverse-zone", dest="reverse_zones",
metavar="REVERSE_ZONE", action="append", default=None,
help="The reverse DNS zone to use. This option can "
"be used multiple times")
parser.add_argument("--no-reverse", dest="no_reverse",
action="store_true",
help="Do not create new reverse DNS zone")
parser.add_argument("--auto-reverse", dest="auto_reverse",
action="store_true",
help="Create necessary reverse zones")
parser.add_argument("--zonemgr", dest="zonemgr",
default=None,
help="DNS zone manager e-mail address. Defaults to "
"hostmaster@DOMAIN")
parser.add_argument("--forwarder", dest="forwarders",
action="append", default=None,
help="Add a DNS forwarder. This option can be used "
"multiple times")
parser.add_argument("--no-forwarders", dest="no_forwarders",
action="store_true",
help="Do not add any DNS forwarders, use root "
"servers instead")
parser.add_argument("--auto-forwarders", dest="auto_forwarders",
action="store_true",
help="Use DNS forwarders configured in "
"/etc/resolv.conf")
parser.add_argument("-forward-policy-", dest="forward_policy",
choices=("only", "first"), default=None,
help="DNS forwarding policy for global forwarders")
parser.add_argument("--no-dnssec-validation", dest="no_dnssec_validation",
action="store_true",
help="Disable DNSSEC validation")
# ad trust
parser.add_argument("--enable-compat", dest="enable_compat",
action="store_true",
help="Enable support for trusted domains for old "
"clients")
parser.add_argument("--netbios-name", dest="netbios_name",
default=None,
help="NetBIOS name of the IPA domain")
parser.add_argument("--rid-base", dest="rid_base",
default=None, type=int,
help="Start value for mapping UIDs and GIDs to RIDs")
parser.add_argument("--secondary-rid-base", dest="secondary_rid_base",
default=None, type=int,
help="Start value of the secondary range for mapping "
"UIDs and GIDs to RIDs")
# deprecated
parser.add_argument("--domain-level", type=int,
help="IPA domain level (deprecated)")
# uninstall
parser.add_argument("--ignore-topology-disconnect",
dest="ignore_topology_disconnect",
action="store_true",
help="do not check whether server uninstall "
"disconnects the topology (domain level 1+)")
parser.add_argument("--ignore-last-of-role", dest="ignore_last_of_role",
action="store_true",
help="do not check whether server uninstall removes "
"last CA/DNS server or DNSSec master (domain level "
"1+)")
# logging and output
parser.add_argument("-v", "--verbose", dest="verbose",
action="store_true",
help="print debugging information")
parser.add_argument("-d", "--debug", dest="verbose",
action="store_true",
help="alias for --verbose (deprecated)")
parser.add_argument("-q", "--quiet", dest="quiet",
action="store_true",
help="output only errors")
parser.add_argument("--log-file", dest="log_file",
help="log to the given file")
# ansible
parser.add_argument("--ipaserver-install-packages",
dest="ipaserver_install_packages",
choices=("yes", "no"), default=None,
help="The bool value defines if the needed packages "
"are installed on the node. Default: yes")
parser.add_argument("--ipaserver-setup-firewalld",
dest="ipaserver_setup_firewalld",
choices=("yes", "no"), default=None,
help="The value defines if the needed services will "
"automatically be openen in the firewall managed by "
"firewalld. Default: yes")
parser.add_argument("--ipaserver-external-cert-files-from-controller",
dest="ipaserver_external_cert_files_from_controller",
default=None, action="append",
help="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.")
parser.add_argument("--ipaserver-copy-csr-to-controller",
dest="ipaserver_copy_csr_to_controller",
choices=("yes", "no"), default=None,
help="Copy the generated CSR from the ipaserver to "
"the controller as -ipa.csr.")
# playbook
parser.add_argument("--playbook-dir",
dest="playbook_dir",
default=None,
help="If defined will be used as to create inventory "
"file and playbook in. The files will not be removed "
"after the playbook processing ended.")
parser.add_argument("--become-method",
dest="become_method",
default="sudo",
help="privilege escalation method to use "
"(default=sudo), use `ansible-doc -t become -l` to "
"list valid choices.")
parser.add_argument("--ansible-verbose",
dest="ansible_verbose",
type=int, default=None,
help="privilege escalation method to use "
"(default=sudo), use `ansible-doc -t become -l` to "
"list valid choices.")
options, args = parser.parse_known_args()
if options.playbook_dir and not os.path.isdir(options.playbook_dir):
parser.error("playbook dir does not exist")
if options.log_file:
parser.error("log_file is not supported")
if len(args) < 1:
parser.error("ansible host not set")
elif len(args) > 1:
parser.error("too many arguments: %s" % ",".join(args))
return options, args
def run_cmd(args):
"""
Execute an external command.
"""
p_out = subprocess.PIPE
p_err = subprocess.STDOUT
try:
p = subprocess.Popen(args, stdout=p_out, stderr=p_err,
close_fds=True, bufsize=1,
universal_newlines=True)
while True:
line = p.stdout.readline()
if p.poll() is not None and line == "":
break
sys.stdout.write(line)
except KeyboardInterrupt:
p.wait()
raise
else:
p.wait()
return p.returncode
def main(options, args):
if options.playbook_dir:
playbook_dir = options.playbook_dir
else:
temp_dir = tempfile.mkdtemp(prefix='ansible-ipa-server')
playbook_dir = temp_dir
inventory = os.path.join(playbook_dir, "ipaserver-inventory")
playbook = os.path.join(playbook_dir, "ipaserver-playbook.yml")
with open(inventory, 'w') as f:
f.write("[ipaserver]\n")
f.write("%s\n" % args[0])
f.write("\n")
f.write("[ipaserver:vars]\n")
# basic
if options.dm_password:
f.write("ipadm_password=%s\n" % options.dm_password)
if options.admin_password:
f.write("ipaadmin_password=%s\n" % options.admin_password)
if options.ip_addresses:
f.write("ipaserver_ip_addresses=%s\n" %
",".join(options.ip_addresses))
if options.domain:
f.write("ipaserver_domain=%s\n" % options.domain)
if options.realm:
f.write("ipaserver_realm=%s\n" % options.realm)
if options.hostname:
f.write("ipaserver_hostname=%s\n" % options.hostname)
if options.ca_cert_file:
f.write("ipaserver_ca_cert_files=%s\n" % options.ca_cert_file)
if options.pki_config_override:
f.write("ipaserver_pki_config_override=yes\n")
if options.no_host_dns:
f.write("ipaserver_no_host_dns=yes\n")
# server
if options.setup_adtrust:
f.write("ipaserver_setup_adtrust=yes\n")
if options.setup_kra:
f.write("ipaserver_setup_kra=yes\n")
if options.setup_dns:
f.write("ipaserver_setup_dns=yes\n")
if options.idstart:
f.write("ipaserver_idstart=%s\n" % options.idstart)
if options.idmax:
f.write("ipaserver_idmax=%s\n" % options.idmax)
if options.no_hbac_allow:
f.write("ipaserver_no_hbac_allow=yes\n")
if options.no_pkinit:
f.write("ipaserver_no_pkinit=yes\n")
if options.no_ui_redirect:
f.write("ipaserver_no_ui_redirect=yes\n")
if options.dirsrv_config_file:
f.write("ipaserver_dirsrv_config_file=%s\n" %
options.dirsrv_config_file)
# ssl certificate
if options.dirsrv_cert_files:
f.write("ipaserver_dirsrv_cert_files=%s\n" %
",".join(options.dirsrv_cert_files))
if options.http_cert_files:
f.write("ipaserver_http_cert_files=%s\n" %
",".join(options.http_cert_files))
if options.pkinit_cert_files:
f.write("ipaserver_pkinit_cert_files=%s\n" %
",".join(options.pkinit_cert_files))
if options.dirsrv_pin:
f.write("ipaserver_dirsrv_pin=%s\n" % options.dirsrv_pin)
if options.http_pin:
f.write("ipaserver_http_pin=%s\n" % options.http_pin)
if options.pkinit_pin:
f.write("ipaserver_pkinit_pin=%s\n" % options.pkinit_pin)
if options.dirsrv_cert_name:
f.write("ipaserver_dirsrv_cert_name=%s\n" %
options.dirsrv_cert_name)
if options.http_cert_name:
f.write("ipaserver_http_cert_name=%s\n" % options.http_cert_name)
if options.pkinit_cert_name:
f.write("ipaserver_pkinit_cert_name=%s\n" %
options.pkinit_cert_name)
# client
if options.mkhomedir:
f.write("ipaclient_mkhomedir=yes\n")
if options.ntp_servers:
f.write("ipaclient_ntp_servers=%s\n" %
",".join(options.ntp_servers))
if options.ntp_pool:
f.write("ipaclient_ntp_pool=%s\n" % options.ntp_pool)
if options.no_ntp:
f.write("ipaclient_no_ntp=yes\n")
if options.ssh_trust_dns:
f.write("ipaclient_ssh_trust_dns=yes\n")
if options.no_ssh:
f.write("ipaclient_no_ssh=yes\n")
if options.no_sshd:
f.write("ipaclient_no_sshd=yes\n")
if options.no_dns_sshfp:
f.write("ipaclient_no_dns_sshfp=yes\n")
# certificate system
if options.external_ca:
f.write("ipaserver_external_ca=yes\n")
if options.external_ca_type:
f.write("ipaserver_external_ca_type=%s\n" %
options.external_ca_type)
if options.external_ca_profile:
f.write("ipaserver_external_ca_profile=%s\n" %
options.external_ca_profile)
if options.external_cert_files:
f.write("ipaserver_external_cert_files=%s\n" %
",".join(options.external_cert_files))
if options.subject_base:
f.write("ipaserver_subject_base=%s\n" % options.subject_base)
if options.ca_subject:
f.write("ipaserver_ca_subject=%s\n" % options.ca_subject)
if options.ca_signing_algorithm:
f.write("ipaserver_ca_signing_algorithm=%s\n" %
options.ca_signing_algorithm)
# dns
if options.allow_zone_overlap:
f.write("ipaserver_allow_zone_overlap=yes\n")
if options.reverse_zones:
f.write("ipaserver_reverse_zones=%s\n" %
",".join(options.reverse_zones))
if options.no_reverse:
f.write("ipaserver_no_reverse=yes\n")
if options.auto_reverse:
f.write("ipaserver_auto_reverse=yes\n")
if options.zonemgr:
f.write("ipaserver_zonemgr=%s\n" % options.zonemgr)
if options.forwarders:
f.write("ipaserver_forwarders=%s\n" %
",".join(options.forwarders))
if options.no_forwarders:
f.write("ipaserver_no_forwarders=yes\n")
if options.auto_forwarders:
f.write("ipaserver_auto_forwarders=yes\n")
if options.forward_policy:
f.write("ipaserver_forward_policy=%s\n" % options.forward_policy)
if options.no_dnssec_validation:
f.write("ipaserver_no_dnssec_validation=yes\n")
# ad trust
if options.enable_compat:
f.write("ipaserver_enable_compat=yes\n")
if options.netbios_name:
f.write("ipaserver_netbios_name=%s\n" % options.netbios_name)
if options.rid_base:
f.write("ipaserver_rid_base=%s\n" % options.rid_base)
if options.secondary_rid_base:
f.write("ipaserver_secondary_rid_base=%s\n" %
options.secondary_rid_base)
# uninstall
if options.ignore_topology_disconnect:
f.write("ipaserver_ignore_topology_disconnect=yes\n")
if options.ignore_last_of_role:
f.write("ipaserver_ignore_last_of_role=yes\n")
# ansible
if options.ipaserver_install_packages:
f.write("ipaserver_install_packages=%s\n" %
options.ipaserver_install_packages)
if options.ipaserver_setup_firewalld:
f.write("ipaserver_setup_firewalld=%s\n" %
options.ipaserver_setup_firewalld)
if options.ipaserver_external_cert_files_from_controller:
f.write("ipaserver_external_cert_files_from_controller=%s\n" %
",".join(
options.ipaserver_external_cert_files_from_controller))
if options.ipaserver_copy_csr_to_controller:
f.write("ipaserver_copy_csr_to_controller=%s\n" %
options.ipaserver_copy_csr_to_controller)
if options.uninstall:
state = "absent"
else:
state = "present"
with open(playbook, 'w') as f:
f.write("---\n")
f.write("- name: Playbook to configure IPA server\n")
f.write(" hosts: ipaserver\n")
f.write(" become: true\n")
if options.become_method:
f.write(" become_method: %s\n" % options.become_method)
f.write("\n")
f.write(" roles:\n")
f.write(" - role: ipaserver\n")
f.write(" state: %s\n" % state)
cmd = [ 'ansible-playbook' ]
if options.ansible_verbose:
cmd.append("-"+"v"*options.ansible_verbose)
cmd.extend(['-i', inventory, playbook])
try:
returncode = run_cmd(cmd)
if returncode != 0:
raise RuntimeError()
finally:
if not options.playbook_dir:
shutil.rmtree(temp_dir, ignore_errors=True)
options, args = parse_options()
try:
main(options, args)
except KeyboardInterrupt:
sys.exit(1)
except SystemExit as e:
sys.exit(e)
except RuntimeError as e:
sys.exit(e)
except Exception as e:
if options.verbose:
traceback.print_exc(file=sys.stdout)
else:
print("Re-run %s with --verbose option to get more information" %
sys.argv[0])
print("Unexpected error: %s" % str(e))
sys.exit(1)
ansible-freeipa-v1.7.0/utils/build-galaxy-release.sh 0000775 0000000 0000000 00000012551 14232747165 0022451 0 ustar 00root root 0000000 0000000 #!/bin/bash
#
# Build Ansible Collection from ansible-freeipa repo
#
prog=$(basename "$0")
pwd=$(pwd)
usage() {
cat </dev/null | sed -e "s/^v//")
if [ -z "$galaxy_version" ]; then
echo "Version could not be detected"
exit 1
fi
echo "Builing galaxy release: ${namespace}-${collection}-${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: \"$collection\"/" galaxy.yml
find . -name "*~" -exec rm {} \;
sed -i -e "s/ansible.module_utils.ansible_freeipa_module/ansible_collections.${collection_prefix}.plugins.module_utils.ansible_freeipa_module/" plugins/modules/*.py
(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 .
})
[ ! -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
ansible-freeipa-v1.7.0/utils/build-srpm.sh 0000775 0000000 0000000 00000001043 14232747165 0020521 0 ustar 00root root 0000000 0000000 #!/bin/bash
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-v1.7.0/utils/changelog 0000775 0000000 0000000 00000007757 14232747165 0020003 0 ustar 00root root 0000000 0000000 #!/usr/bin/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
usage = "Usage: changelog [options] []"
parser = argparse.ArgumentParser(usage=usage)
parser.add_argument("--tag", dest="tag",
help="git tag")
options, args = parser.parse_known_args()
if len(args) == 1:
new_version = args[0]
elif len(args) != 0:
parser.error("new version is not set")
else:
new_version = None
if options.tag is None:
tag = subprocess.check_output(
"git describe --tags $(git rev-list --tags --max-count=1)",
shell=True)
options.tag = tag.decode("utf-8").strip()
version = options.tag[1:]
command = ["git", "log", "%s.." % options.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)
if new_version is not None:
s = "ansible-freeipa-%s" % new_version
print(s)
print("=" * len(s))
print()
commits = {}
prs = {}
authors = {}
lines = process.stdout.decode("utf-8").split("\n")
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 = int(msg[0].split()[3][1:])
if len(msg) > 1:
prs[pr] = msg[1].strip()
else:
prs[pr] = 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
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)
s = "Changes since %s" % version
print("%s" % s)
print("-" * len(s))
print()
prs_sorted = sorted(prs.keys(), reverse=True)
for pr in prs_sorted:
if isinstance(prs[pr], Ref):
msg = get_commit(commits, prs[pr].commit)
else:
msg = prs[pr]
print(" - %s (#%d)" % (msg, pr))
print()
s = "Detailed changelog since %s by author" % version
print("%s" % s)
print("-" * len(s))
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()
ansible-freeipa-v1.7.0/utils/galaxyfy-README.py 0000664 0000000 0000000 00000003660 14232747165 0021244 0 ustar 00root root 0000000 0000000 #!/usr/bin/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-v1.7.0/utils/galaxyfy-module-EXAMPLES.py 0000664 0000000 0000000 00000004066 14232747165 0023011 0 ustar 00root root 0000000 0000000 #!/usr/bin/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 module_EXAMPLES(module_in, project_prefix, collection_prefix):
out_lines = []
with open(module_in) as in_f:
changed = False
example = False
example_lines = []
for line in in_f:
stripped = line.strip()
if stripped in ['EXAMPLES = """', "EXAMPLES = '''"]:
example = True
out_lines.append(line)
continue
elif example and stripped in ["'''", '"""']:
_out_lines, _changed = \
galaxyfy_playbook(project_prefix, collection_prefix,
example_lines)
for _line in _out_lines:
out_lines.append(_line)
example_lines = []
if _changed:
changed = True
example = False
out_lines.append(line)
continue
if example:
example_lines.append(line)
else:
out_lines.append(line)
if changed:
with open(module_in, "w") as out_f:
for line in out_lines:
out_f.write(line)
module_EXAMPLES(sys.argv[1], sys.argv[2], sys.argv[3])
ansible-freeipa-v1.7.0/utils/galaxyfy-playbook.py 0000664 0000000 0000000 00000002436 14232747165 0022127 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019,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 playbook(playbook_in, project_prefix, collection_prefix):
changed = False
with open(playbook_in) as in_f:
lines = in_f.readlines()
out_lines, changed = \
galaxyfy_playbook(project_prefix, collection_prefix, lines)
if changed:
with open(playbook_in, "w") as out_f:
for line in out_lines:
out_f.write(line)
playbook(sys.argv[1], sys.argv[2], sys.argv[3])
ansible-freeipa-v1.7.0/utils/galaxyfy.py 0000664 0000000 0000000 00000004657 14232747165 0020320 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner
#
# Copyright (C) 2019,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 re
def galaxyfy_playbook(project_prefix, collection_prefix, lines):
po1 = re.compile('(%s.*:)$' % project_prefix)
po2 = re.compile('(.*:) (%s.*)$' % project_prefix)
out_lines = []
pattern1 = r'%s.\1' % collection_prefix
pattern2 = r'\1 %s.\2' % collection_prefix
changed = False
changeable = False
include_role = False
for line in lines:
stripped = line.strip()
if stripped.startswith("- name:") or \
stripped.startswith("- block:"):
changeable = True
elif stripped in ["set_fact:", "vars:"]:
changeable = False
include_role = False
elif stripped == "roles:":
changeable = True
include_role = False
elif stripped.startswith("include_role:"):
include_role = True
elif include_role and stripped.startswith("name:"):
line = po2.sub(pattern2, line)
changed = True
elif changeable and stripped.startswith("- role:"):
line = po2.sub(pattern2, line)
changed = True
elif (changeable and stripped.startswith(project_prefix)
and not stripped.startswith(collection_prefix) # noqa
and stripped.endswith(":")): # noqa
line = po1.sub(pattern1, line)
changed = True
changeable = False # Only change first line in task
elif (stripped.startswith("- %s" % project_prefix)
and stripped.endswith(":")): # noqa
line = po1.sub(pattern1, line)
changed = True
out_lines.append(line)
return (out_lines, changed)
ansible-freeipa-v1.7.0/utils/gen_module_docs.py 0000664 0000000 0000000 00000031340 14232747165 0021607 0 ustar 00root root 0000000 0000000 import sys
param_docs = {
"ccache": "The local ccache",
"installer_ccache": "The installer ccache setting",
"_top_dir": "The installer _top_dir setting",
"_ca_enabled": "The installer _ca_enabled setting",
"_add_to_ipaservers": "The installer _add_to_ipaservers setting",
"_ca_subject": "The installer _ca_subject setting",
"_subject_base": "The installer _subject_base setting",
"config_setup_ca": "The config setup_ca setting",
"config_master_host_name": "The config master_host_name setting",
"config_ca_host_name": "The config ca_host_name setting",
"config_ips": "The config ips setting",
"_ca_file": "The installer _ca_file setting",
"_kra_enabled": "The installer _kra_enabled setting",
"_dirsrv_pkcs12_info": "The installer _dirsrv_pkcs12_info setting",
"_pkinit_pkcs12_info": "The installer _pkinit_pkcs12_info setting",
"_http_pkcs12_info": "The installer _http_pkcs12_info setting",
"ds_ca_subject": "The ds.ca_subject setting",
"ca_subject": "The installer ca_subject setting",
"_hostname_overridden": "The installer _hostname_overridden setting",
"_kra_host_name": "The installer _kra_host_name setting",
"_http_ca_cert": "The installer _http_ca_cert setting",
"_update_hosts_file": "The installer _update_host_file setting",
"sssd": "The installer sssd setting",
"dnsok": "The installer dnsok setting",
"dm_password": "Directory Manager password",
"password": "Admin user kerberos password",
"ip_addresses": "List of Master Server IP Addresses",
"domain": "Primary DNS domain of the IPA deployment",
"realm": "Kerberos realm name of the IPA deployment",
"hostname": "Fully qualified name of this host",
"ca_cert_file": [
"A CA certificate to use. Do not acquire the IPA CA certificate via",
"automated means"
],
"ca_cert_files": [
"List of files containing CA certificates for the service certificate",
"files"
],
"no_host_dns": "Do not use DNS for hostname lookup during installation",
"setup_adtrust": "Configure AD trust capability",
"setup_ca": "Configure a dogtag CA",
"setup_kra": "Configure a dogtag KRA",
"setup_dns": "Configure bind with our zone",
"force_join": "Force client enrollment even if already enrolled",
"subject_base": [
"The certificate subject base (default O=).",
"RDNs are in LDAP order (most specific RDN first)."
],
"server": "Fully qualified name of IPA server to enroll to",
"dirman_password": "Directory Manager (master) password",
"no_pkinit": "Disable pkinit setup steps",
"no_ui_redirect": "Do not automatically redirect to the Web UI",
"external_ca": "External ca setting",
"external_cert_files": [
"File containing the IPA CA certificate and the external CA "
"certificate chain"
],
"reverse_zones": "The reverse DNS zones to use",
"no_reverse": "Do not create new reverse DNS zone",
"auto_reverse": "Create necessary reverse zones",
"forwarders": "Add DNS forwarders",
"no_forwarders": "Do not add any DNS forwarders, use root servers instead",
"auto_forwarders": "Use DNS forwarders configured in /etc/resolv.conf",
"forward_policy": "DNS forwarding policy for global forwarders",
"enable_compat": "Enable support for trusted domains for old clients",
"netbios_name": "NetBIOS name of the IPA domain",
"rid_base": "Start value for mapping UIDs and GIDs to RIDs",
"secondary_rid_base": [
"Start value of the secondary range for mapping UIDs and GIDs to RIDs"
],
"pki_config_override": "Path to ini file with config overrides",
"servers": "Fully qualified name of IPA servers to enroll to",
"hidden_replica": "Install a hidden replica",
"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"
],
"dirsrv_cert_files": [
"Files containing the Directory Server SSL certificate and private key"
],
"http_cert_files": [
"File containing the Apache Server SSL certificate and private key"
],
"pkinit_cert_files": [
"File containing the Kerberos KDC SSL certificate and private key"
],
"no_ntp": "Do not configure ntp",
"ntp_servers": "ntp servers to use",
"ntp_pool": "ntp server pool to use",
"no_dnssec_validation": "Disable DNSSEC validation",
"master": "Master host name",
"master_password": "kerberos master password (normally autogenerated)",
"principal": [
"User Principal allowed to promote replicas and join IPA realm"
],
"dirsrv_pin": "The password to unlock the Directory Server private key",
"http_pin": "The password to unlock the Apache Server private key",
"pkinit_pin": "The password to unlock the Kerberos KDC private key",
"dirsrv_cert_name":
"Name of the Directory Server SSL certificate to install",
"http_cert_name": "Name of the Apache Server SSL certificate to install",
"pkinit_cert_name": "Name of the Kerberos KDC SSL certificate to install",
"keytab": "Path to backed up keytab from previous enrollment",
"mkhomedir": "Create home directories for users on their first login",
"adtrust_netbios_name": "The adtrust netbios_name setting",
"adtrust_reset_netbios_name": "The adtrust reset_netbios_name setting",
"zonemgr":
"DNS zone manager e-mail address. Defaults to hostmaster@DOMAIN",
"ssh_trust_dns": "Configure OpenSSH client to trust DNS SSHFP records",
"dns_ip_addresses": "The dns ip_addresses setting",
"dns_reverse_zones": "The dns reverse_zones setting",
"no_ssh": "Do not configure OpenSSH client",
"no_sshd": "Do not configure OpenSSH server",
"no_dns_sshfp": "Do not automatically create DNS SSHFP records",
"allow_zone_overlap": "Create DNS zone even if it already exists",
"skip_conncheck": "Skip connection check to remote master",
"idstart": "The starting value for the IDs range (default random)",
"idmax": "The max value for the IDs range (default idstart+199999)",
"no_hbac_allow": "Don't install allow_all HBAC rule",
"domainlevel": "The domain level",
"external_ca_type": "Type of the external CA",
"external_ca_profile": [
"Specify the certificate profile/template to use at the external CA"
],
"force": "Installer force parameter",
"ca_signing_algorithm": "Signing algorithm of the IPA CA certificate",
"debug": "Turn on extra debugging",
"basedn": "The basedn of the IPA server (of the form dc=example,dc=com)",
"allow_repair": [
"Allow repair of already joined hosts. Contrary to "
"ipaclient_force_join the host entry will not be changed on the server"
],
"backup": "File to backup",
"fqdn": [
"The fully-qualified hostname of the host to add/modify/remove"
],
"certificates": "A list of host certificates",
"sshpubkey": "The SSH public key for the host",
"ipaddress": "The IP address for the host",
"random": "Generate a random password to be used in bulk enrollment",
"state": "The desired host state",
"kdc": "The name or address of the host running the KDC",
"admin_keytab": "The path to a local admin keytab",
"kinit_attempts": "Repeat the request for host Kerberos ticket X times",
"automount_location": "The automount location",
"firefox_dir": [
"Specify directory where Firefox is installed (for example",
"'/usr/lib/firefox')"
],
"client_domain": "Primary DNS domain of the IPA deployment",
"nisdomain": "The NIS domain name",
"ca_enabled": "Whether the Certificate Authority is enabled or not",
"on_master": "Whether the configuration is done on the master or not",
"enable_dns_updates": [
"Configures the machine to attempt dns updates when the ip address",
"changes"
],
"all_ip_addresses": [
"All routable IP addresses configured on any interface will be added",
"to DNS"
],
"request_cert": "Request certificate for the machine",
"preserve_sssd": "Preserve old SSSD configuration if possible",
"no_sudo": "Do not configure SSSD as data source for sudo",
"fixed_primary":
"Configure sssd to use fixed server as primary IPA server",
"permit": "Disable access rules by default, permit all access",
"no_krb5_offline_passwords": [
"Configure SSSD not to store user password when the server is offline"
],
"force_ntpd": [
"Stop and disable any time&date synchronization services besides ntpd",
"Deprecated since 4.7"
],
"no_nisdomain": "Do not configure NIS domain name",
"configure_firefox": "Configure Firefox to use IPA domain credentials",
}
def gen_module_docs(module_in):
with open(module_in) as in_f:
in_lines = in_f.readlines()
arg_spec = False
args = []
i = 0
while i < len(in_lines):
line = in_lines[i]
stripped = line.strip()
# print("stripped: %s" % repr(stripped))
if stripped.startswith("# "):
pass
elif stripped.startswith("argument_spec=dict()"):
pass
elif stripped.startswith("argument_spec=dict("):
arg_spec = True
elif stripped.startswith("),") and arg_spec:
arg_spec = False
elif arg_spec:
# if not "dict=(" in stripped:
# print("%s: Bad argument dict line '%s'" % (module_in,
# stripped))
while ")," not in stripped and i < len(in_lines) - 1:
next_stripped = in_lines[i + 1].strip()
if not next_stripped.startswith("# "):
stripped += next_stripped
i += 1
# print("stripped: '%s'" % stripped)
try:
param, _dict = stripped.split("=", 1)
except Exception:
print("Failed to split line '%s'" % stripped)
sys.exit(1)
# print("_dict: '%s'" % _dict)
if not _dict.startswith("dict(") or not _dict.endswith("),"):
print("%s: Bad argument dict line 2 '%s'" % (module_in, _dict))
sys.exit(1)
else:
_dict = _dict[5:-2]
if param not in param_docs:
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
print("%s: param '%s' is not in param_docs" % (module_in,
param))
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
sys.exit(1)
# print("param: '%s', dict: '%s'" % (param, _dict))
opts = _dict.split(',')
opts = [o.strip() for o in opts]
required = False
# no_log = False
if "required=True" in opts:
required = True
# if "no_log=True" in opts:
# no_log = True
# args.append([param, required, no_log])
args.append([param, required])
i += 1
# print("%s: %s" % (module_in, repr(args)))
def add_options(args):
for param, required in args:
out_lines.append(" %s:\n" % param)
if isinstance(param_docs[param], list):
out_lines.append(" description:\n")
for x in param_docs[param]:
out_lines.append(" %s\n" % x)
else:
out_lines.append(" description: %s\n" % param_docs[param])
out_lines.append(" required: %s\n" % ("yes", "no")[required])
out_lines = []
options = False
in_options = False
changed = False
docs = False
for line in in_lines:
stripped = line.strip()
if stripped.startswith("DOCUMENTATION = '''"):
docs = True
elif stripped.startswith("options:"):
out_lines.append(line)
add_options(args)
options = True
in_options = True
changed = True
continue
elif stripped.startswith("author:"):
if not options:
add_options(args)
options = True
changed = True
in_options = False
elif stripped.startswith("'''"):
if not options:
add_options(args)
options = True
changed = True
in_options = False
docs = False
elif docs and in_options:
continue
out_lines.append(line)
print(module_in)
# for line in out_lines:
# sys.stdout.write(line)
if changed:
with open(module_in, "w") as out_f:
for line in out_lines:
out_f.write(line)
gen_module_docs(sys.argv[1])
ansible-freeipa-v1.7.0/utils/gen_modules_docs.sh 0000664 0000000 0000000 00000000132 14232747165 0021747 0 ustar 00root root 0000000 0000000 #!/bin/bash
for i in roles/ipa*/*/*.py; do
python utils/gen_module_docs.py "$i"
done
ansible-freeipa-v1.7.0/utils/lint_check.sh 0000775 0000000 0000000 00000002226 14232747165 0020552 0 ustar 00root root 0000000 0000000 #!/bin/bash
INFO="\033[37;1m"
WARN="\033[33;1m"
RST="\033[0m"
topdir=$(dirname "$0")
pushd "${topdir}/.." >/dev/null 2>&1 || exit 1
echo -e "${INFO}Running 'flake8'...${RST}"
flake8 plugins utils roles setup.py
echo -e "${INFO}Running 'pydocstyle'...${RST}"
pydocstyle plugins utils roles setup.py
echo -e "${INFO}Running 'pylint'...${RST}"
pylint plugins roles setup.py
ANSIBLE_LIBRARY="${ANSIBLE_LIBRARY:-plugins/modules}"
ANSIBLE_MODULE_UTILS="${ANSIBLE_MODULE_UTILS:-plugins/module_utils}"
ANSIBLE_DOC_FRAGMENT_PLUGINS="${ANSIBLE_DOC_FRAGMENT_PLUGINS:-plugins/doc_fragments}"
export ANSIBLE_LIBRARY ANSIBLE_MODULE_UTILS ANSIBLE_DOC_FRAGMENT_PLUGINS
echo -e "${WARN}Missing file warnings are expected and can be ignored.${RST}"
echo -e "${INFO}Running 'ansible-lint'...${RST}"
playbook_dirs=(
"tests"
"playbooks"
)
ansible-lint --force-color "${playbook_dirs[@]}"
echo -e "${INFO}Running 'ansible-doc-test'...${RST}"
python "${topdir}/ansible-doc-test" -v roles plugins
echo -e "${INFO}Running 'yamllint'...${RST}"
yaml_dirs=(
"tests"
"playbooks"
"molecule"
"roles"
)
yamllint -f colored "${yaml_dirs[@]}"
popd >/dev/null 2>&1 || exit 1
ansible-freeipa-v1.7.0/utils/new_module 0000775 0000000 0000000 00000010671 14232747165 0020177 0 ustar 00root root 0000000 0000000 #!/bin/bash
# -*- 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 .
prog="$(basename "$0")"
topdir="$(dirname "$0")"
function usage() {
cat <
Create new ansible-freeipa module using templates.
Options:
-m Create module with member support
-f Force creation
-h Print this help
EOF
}
member=0
force=0
while getopts "mfh" arg; do
case $arg in
m) member=1;;
f) force=1;;
h)
usage;
exit 0
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
for (( i=0; i "$d"
}
# MODULE
dest=plugins/modules
mkdir -p "$dest"
src=ipamodule.py.in
[ "$member" == "1" ] && src=ipamodule+member.py.in
template "$src" "$dest/ipa$name.py"
# README
src=README-module.md.in
[ "$member" == "1" ] && src=README-module+member.md.in
template "$src" "README-$name.md"
# PLAYBOOKS
dest="playbooks/$name"
mkdir -p "$dest"
template module-present.yml.in "$dest/$name-present.yml"
template module-absent.yml.in "$dest/$name-absent.yml"
if [ "$member" == "1" ]; then
template module-member-present.yml.in "$dest/$name-member-present.yml"
template module-member-absent.yml.in "$dest/$name-member-absent.yml"
fi
# TESTS
dest="tests/$name"
mkdir -p "$dest"
src=test_module.yml.in
[ "$member" == "1" ] && src=test_module+member.yml.in
template "$src" "$dest/test_$name.yml"
template test_module_client_context.yml.in "$dest/test_${name}_client_context.yml"
ansible-freeipa-v1.7.0/utils/templates/ 0000775 0000000 0000000 00000000000 14232747165 0020104 5 ustar 00root root 0000000 0000000 ansible-freeipa-v1.7.0/utils/templates/README-module+member.md.in 0000664 0000000 0000000 00000005252 14232747165 0024522 0 ustar 00root root 0000000 0000000 ${name^} module
============
Description
-----------
The $name module allows to ensure presence and absence of ${name}s and $name members.
Features
--------
* ${name^} management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipa$name module.
Requirements
------------
**Controller**
* Ansible version: 2.8+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure $name "NAME" is present:
```yaml
---
- name: Playbook to manage IPA $name.
hosts: ipaserver
become: no
tasks:
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
# Add needed parameters here
```
Example playbook to make sure $name "NAME" member PARAMETER2 VALUE is present:
```yaml
---
- name: Playbook to manage IPA $name PARAMETER2 member.
hosts: ipaserver
become: no
tasks:
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
PARAMETER2: VALUE
action: member
```
Example playbook to make sure $name "NAME" member PARAMETER2 VALUE is absent:
```yaml
---
- name: Playbook to manage IPA $name PARAMETER2 member.
hosts: ipaserver
become: no
tasks:
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
PARAMETER2: VALUE
action: member
state: absent
```
Example playbook to make sure $name "NAME" is absent:
```yaml
---
- name: Playbook to manage IPA $name.
hosts: ipaserver
become: no
tasks:
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
state: absent
```
MORE EXAMPLE PLAYBOOKS HERE
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` \| `ALIAS` | The list of $name name strings. | yes
`PARAMETER1` \| `API_PARAMETER_NAME` | DESCRIPTION | BOOL
`PARAMETER2` \| `API_PARAMETER_NAME` | DESCRIPTION | BOOL
`action` | Work on $name or member level. It can be on of `member` or `$name` and defaults to `$name`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
$author
ansible-freeipa-v1.7.0/utils/templates/README-module.md.in 0000664 0000000 0000000 00000003643 14232747165 0023261 0 ustar 00root root 0000000 0000000 ${name^} module
============
Description
-----------
The $name module allows to ensure presence and absence of ${name}s.
Features
--------
* ${name^} management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipa$name module.
Requirements
------------
**Controller**
* Ansible version: 2.8+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to make sure $name "NAME" is present:
```yaml
---
- name: Playbook to manage IPA $name.
hosts: ipaserver
become: no
tasks:
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
# Add needed parameters here
```
Example playbook to make sure $name "NAME" is absent:
```yaml
---
- name: Playbook to manage IPA $name.
hosts: ipaserver
become: no
tasks:
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
state: absent
```
MORE EXAMPLE PLAYBOOKS HERE
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` \| `ALIAS` | The list of $name name strings. | yes
`PARAMETER1` \| `API_PARAMETER_NAME` | DESCRIPTION | BOOL
`PARAMETER2` \| `API_PARAMETER_NAME` | DESCRIPTION | BOOL
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
$author
ansible-freeipa-v1.7.0/utils/templates/ipamodule+member.py.in 0000664 0000000 0000000 00000023603 14232747165 0024311 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# $author <$email>
#
# Copyright (C) $year 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: ipa$name
short description: Manage FreeIPA $name
description: Manage FreeIPA $name and $name members
extends_documentation_fragment:
- ipamodule_base_docs
- ipamoudle_base_docs.delete_continue
options:
name:
description: The list of $name name strings.
required: true
aliases: ["API_PARAMETER_NAME"]
PARAMETER1:
description: DESCRIPTION
required: REQUIRED
aliases: ["API_PARAMETER_NAME"]
PARAMETER2:
description: member DESCRIPTION
required: REQUIRED
aliases: ["API_PARAMETER_NAME"]
action:
description: Work on $name or member level.
choices: ["$name", "member"]
default: $name
required: false
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
required: true
"""
EXAMPLES = """
# Ensure $name NAME is present
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
PARAMETERS
# Ensure $name "NAME" member PARAMETER2 VALUE is present
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
PARAMETER2: VALUE
action: member
# Ensure $name "NAME" member PARAMETER2 VALUE is absent
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
PARAMETER2: VALUE
action: member
state: absent
# Ensure $name NAME is absent
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
state: absent
# Ensure $name NAME ...
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
CHANGE PARAMETERS
"""
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_$name(module, name):
"""Find if a $name with the given name already exist."""
try:
_result = module.ipa_command("$name_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if $name name is not found.
return None
else:
return _result["result"]
def gen_args(PARAMETER1):
_args = {}
if PARAMETER1 is not None:
_args["API_PARAMETER1_NAME"] = PARAMETER1
return _args
def gen_member_args(PARAMETER2):
_args = {}
if PARAMETER2 is not None:
_args["API_PARAMETER2_NAME"] = PARAMETER2
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", aliases=["API_PARAMETER_NAME"],
default=None, required=True),
# present
PARAMETER1=dict(required=False, type='str',
aliases=["API_PARAMETER_NAME"], default=None),
PARAMETER2=dict(required=False, type='list',
aliases=["API_PARAMETER_NAME"], default=None),
action=dict(type="str", default="$name",
choices=["member", "$name"]),
# 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
PARAMETER1 = ansible_module.params_get("PARAMETER1")
# Note: some parameters must be compared in a case insensitive way,
# or are transliterated into its lowercase version by IPA API. For
# these parameters, use IPAAnsibleModule.params_get_lowercase.
PARAMETER2 = ansible_module.params_get_lowercase("PARAMETER2")
action = ansible_module.params_get("action")
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 $name can be added at a time.")
if action == "member":
invalid = ["PARAMETER1"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["PARAMETER1"]
if action == "$name":
invalid.append("PARAMETER2")
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 $name exists
res_find = find_$name(ansible_module, name)
# add/del lists
PARAMETER2_add, PARAMETER2_del = [], []
# Create command
if state == "present":
# Generate args
args = gen_args(PARAMETER1)
if action == "$name":
# Found the $name
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, "$name_mod", args])
else:
commands.append([name, "$name_add", args])
member_args = gen_member_args(PARAMETER2)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
PARAMETER2_add, PARAMETER2_del = gen_add_del_lists(
PARAMETER2, res_find.get("member_PARAMETER2"))
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No $name '%s'" % name)
# Reduce add lists for PARAMETER2
# to new entries only that are not in res_find.
if PARAMETER2 is not None:
PARAMETER2_add = gen_add_list(
PARAMETER2, res_find.get("member_PARAMETER2"))
elif state == "absent":
if action == "$name":
if res_find is not None:
commands.append(
[name, "$name_del", {"continue": delete_continue}]
)
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No $name '%s'" % name)
# Reduce del lists of member_host and member_hostgroup,
# to the entries only that are in res_find.
if PARAMETER2 is not None:
PARAMETER2_del = gen_intersection_list(
PARAMETER2, res_find.get("member_PARAMETER2"))
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Member management
# Add members
if PARAMETER2_add:
commands.append([name, "$name_add_member",
{
"PARAMETER2": PARAMETER2_add,
}])
# Remove members
if PARAMETER2_del:
commands.append([name, "$name_remove_member",
{
"PARAMETER2": PARAMETER2_del,
"continue": delete_continue,
}])
# Execute commands
#
# To handle default member errors there is a static method
# IPAAnsibleModule.handle_member_errors. It can be enabled with
# fail_on_member_failures=True for execute_ipa_commands.
# There might be cases in which this needs to be either done
# manually or extended.
#
# Example:
#
# pylint: disable=unused-argument
# def result_handler(module, result, command, name, args, errors):
# # Get all errors
# IPAAnsibleModule.handle_member_errors(module, result, command,
# name, args, errors)
# if "MY ERROR" in result.get("failed",[]):
# errors.append("My error")
#
# # Execute commands
#
# changed = ansible_module.execute_ipa_commands(commands,
# result_handler)
#
changed = ansible_module.execute_ipa_commands(
commands, fail_on_member_failures=True)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()
ansible-freeipa-v1.7.0/utils/templates/ipamodule.py.in 0000664 0000000 0000000 00000013532 14232747165 0023046 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
# Authors:
# $author <$email>
#
# Copyright (C) $year 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: ipa$name
short description: Manage FreeIPA $name
description: Manage FreeIPA $name
extends_documentation_fragment:
- ipamodule_base_docs
- ipamodule_base_docs.delete_continue
options:
name:
description: The list of $name name strings.
required: true
aliases: ["API_PARAMETER_NAME"]
PARAMETER1:
description: DESCRIPTION
required: REQUIRED
aliases: ["API_PARAMETER_NAME"]
PARAMETER2:
description: DESCRIPTION
required: REQUIRED
aliases: ["API_PARAMETER_NAME"]
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
required: true
"""
EXAMPLES = """
# Ensure $name NAME is present
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
PARAMETERS
# Ensure $name NAME is absent
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
state: absent
# Ensure $name NAME ...
- ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
CHANGE PARAMETERS
"""
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_$name(module, name):
"""Find if a $name with the given name already exist."""
try:
_result = module.ipa_command("$name_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if $name name is not found.
return None
else:
return _result["result"]
def gen_args(PARAMETER1, PARAMETER2):
_args = {}
if PARAMETER1 is not None:
_args["API_PARAMETER1_NAME"] = PARAMETER1
if PARAMETER2 is not None:
_args["API_PARAMETER2_NAME"] = PARAMETER2
return _args
def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", aliases=["API_PARAMETER_NAME"],
default=None, required=True),
# present
PARAMETER1=dict(required=False, type='str',
aliases=["API_PARAMETER_NAME"], default=None),
PARAMETER2=dict(required=False, type='list',
aliases=["API_PARAMETER_NAME"], default=None),
# 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
PARAMETER1 = ansible_module.params_get("PARAMETER1")
# Note: some parameters must be compared in a case insensitive way,
# or are transliterated into its lowercase version by IPA API. For
# these parameters, use IPAAnsibleModule.params_get_lowercase.
PARAMETER2 = ansible_module.params_get_lowercase("PARAMETER2")
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 $name can be added at a time.")
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["PARAMETER1", "PARAMETER2"]
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 $name exists
res_find = find_$name(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(PARAMETER1, PARAMETER2)
# Found the $name
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, "$name_mod", args])
else:
commands.append([name, "$name_add", args])
elif state == "absent":
if res_find is not None:
commands.append(
[name, "$name_del", {"continue": delete_continue}]
)
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-v1.7.0/utils/templates/module-absent.yml.in 0000664 0000000 0000000 00000000322 14232747165 0023770 0 ustar 00root root 0000000 0000000 ---
- name: ${name^} absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure $name NAME is absent
ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
state: absent
ansible-freeipa-v1.7.0/utils/templates/module-member-absent.yml.in 0000664 0000000 0000000 00000000377 14232747165 0025247 0 ustar 00root root 0000000 0000000 ---
- name: ${name^} absent example
hosts: ipaserver
become: no
tasks:
- name: Ensure $name NAME is absent
ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
PARAMETER2: VALUE
action: member
state: absent
ansible-freeipa-v1.7.0/utils/templates/module-member-present.yml.in 0000664 0000000 0000000 00000000364 14232747165 0025447 0 ustar 00root root 0000000 0000000 ---
- name: ${name^} member present example
hosts: ipaserver
become: no
tasks:
- name: Ensure $name NAME is present
ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
PARAMETER2: VALUE
action: member
ansible-freeipa-v1.7.0/utils/templates/module-present.yml.in 0000664 0000000 0000000 00000000343 14232747165 0024177 0 ustar 00root root 0000000 0000000 ---
- name: ${name^} present example
hosts: ipaserver
become: no
tasks:
- name: Ensure $name NAME is present
ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
# Add needed parameters here
ansible-freeipa-v1.7.0/utils/templates/test_module+member.yml.in 0000664 0000000 0000000 00000005727 14232747165 0025036 0 ustar 00root root 0000000 0000000 ---
- name: Test $name
hosts: "{{ ipa_test_host | default('ipaserver') }}"
# Change "become" or "gather_facts" to "yes",
# if you test playbook requires any.
become: no
gather_facts: no
tasks:
# CLEANUP TEST ITEMS
- name: Ensure $name NAME is absent
ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
state: absent
# CREATE TEST ITEMS
# TESTS
- name: Ensure $name NAME is present
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
# Add needed parameters here
register: result
failed_when: not result.changed or result.failed
- name: Ensure $name NAME is present again
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
# Add needed parameters here
register: result
failed_when: result.changed or result.failed
- name: Ensure $name NAME member PARAMETER2 VALUE is present
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
PARAMETER2: VALUE
action: member
register: result
failed_when: not result.changed or result.failed
- name: Ensure $name NAME member PARAMETER2 VALUE is present again
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
PARAMETER2: VALUE
action: member
register: result
failed_when: result.changed or result.failed
- name: Ensure $name NAME member PARAMETER2 VALUE is absent
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
PARAMETER2: VALUE
action: member
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure $name NAME member PARAMETER2 VALUE is absent again
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
PARAMETER2: VALUE
action: member
state: absent
register: result
failed_when: result.changed or result.failed
# more tests here
- name: Ensure $name NAME is absent
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure $name NAME is absent again
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
state: absent
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure $name NAME is absent
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
state: absent
ansible-freeipa-v1.7.0/utils/templates/test_module.yml.in 0000664 0000000 0000000 00000003207 14232747165 0023562 0 ustar 00root root 0000000 0000000 ---
- name: Test $name
hosts: "{{ ipa_test_host | default('ipaserver') }}"
# Change "become" or "gather_facts" to "yes",
# if you test playbook requires any.
become: no
gather_facts: no
tasks:
# CLEANUP TEST ITEMS
- name: Ensure $name NAME is absent
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
state: absent
# CREATE TEST ITEMS
# TESTS
- name: Ensure $name NAME is present
ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
# Add needed parameters here
register: result
failed_when: not result.changed or result.failed
- name: Ensure $name NAME is present again
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
# Add needed parameters here
register: result
failed_when: result.changed or result.failed
# more tests here
- name: Ensure $name NAME is absent
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
state: absent
register: result
failed_when: not result.changed or result.failed
- name: Ensure $name NAME is absent again
ipa$name:
ipaadmin_password: SomeADMINpassword
ipaapi_context: "{{ ipa_context | default(omit) }}"
name: NAME
state: absent
register: result
failed_when: result.changed or result.failed
# CLEANUP TEST ITEMS
- name: Ensure $name NAME is absent
ipa$name:
ipaadmin_password: SomeADMINpassword
name: NAME
state: absent
ansible-freeipa-v1.7.0/utils/templates/test_module_client_context.yml.in 0000664 0000000 0000000 00000002430 14232747165 0026661 0 ustar 00root root 0000000 0000000 ---
- name: Test ${name}
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.
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.
ipa${name}:
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 ${name} using client context, in client host.
import_playbook: test_${name}.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test ${name} using client context, in server host.
import_playbook: test_${name}.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']